介绍
sync/atomic库提供了原子操作的支持,原子操作直接有底层CPU硬件支持,因而比一般基于系统API的锁方式效率高效。
原子增、减值
用于对变量值进行原子操作,并返回增加的值
var sum uint32 = 100
for i :=0; i<50;i++{
go func(){
atomic.AddUint32(&sum,1)
}
}
同一时间只有一个goroutine修改sum
比较并交换 Compare And Swap
先比较变量的值是否等于给定旧值,等于旧值的情况下才赋予新值,最后返回新值是否设置成功。
使用锁的做法趋于悲观
我们总假设会有并发的操作要修改被操作的值,并使用锁将相关操作放入临界区中加以保护。
使用CAS操作的做法趋于乐观
总是假设被操作值未曾被改变(即与旧值相等),并一旦确认这个假设的真实性就立即进行值替换
var sum uint32 = 100
for i := uint32(0); i < 100; i++ {
go func(t uint32) {
atomic.CompareAndSwapUint32(&sum, 100, sum+1)
}(i)
}
结果:sum的值只改变了一次,只有当sum值为100的时候,CAS才将sum的值修改为了sum+1
原子导入
赋予变量新值,而不管它原来是什么值。
在原子地存储某个值的过程中,任何CPU都不会进行针对同一个值的读或写操作。
原子的值存储操作总会成功,因为它并不会关心被操作值的旧值是什么。
var val uint32
atomic.StoreUint32(&val, 200)
原子导出
导出变量当前的值。
v:= value 为变量v赋值,但要注意,在进行读取value的操作的过程中,其他对此值的读写操作是可以被同时进行的,那么这个读操作很可能会读取到一个只被修改了一半的数据.
var val uint32 = 100
atomic.LoadUint32(&val)
原子交换值
赋予变量新值,同时返回变量的旧值。
与CAS操作不同,原子交换操作不会关心被操作的旧值。
它会直接设置新值
它会返回被操作值的旧值
var old_val uint32 = 10
var new_val uint32 = 100
atomic.SwapUint32(&old_val,new_val )
网友评论