golang 编程笔记

【golang】使用原子操作优化并发锁同步机制

2020-03-16  本文已影响0人  dongzd

介绍

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 )
上一篇下一篇

猜你喜欢

热点阅读