美文网首页golang 编程笔记
【golang】使用原子操作优化并发锁同步机制

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

作者: dongzd | 来源:发表于2020-03-16 19:53 被阅读0次

    介绍

    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 )
    

    相关文章

      网友评论

        本文标题:【golang】使用原子操作优化并发锁同步机制

        本文链接:https://www.haomeiwen.com/subject/gsjoehtx.html