美文网首页Go
Go sync/atomic包Load和Store并发不安全

Go sync/atomic包Load和Store并发不安全

作者: parker7 | 来源:发表于2018-10-19 14:49 被阅读0次

    前言:为了保证并发安全,go语言中可以使用原子操作。其执行过程不能被中断,这也就保证了同一时刻一个线程的执行不会被其他线程中断,也保证了多线程下数据操作的一致性。

    1.sync/atomic包
    2.Load和Store并发不安全

    1.sync/atomic包

    在atomic包中对几种基础类型提供了原子操作,包括int32,int64,uint32,uint64,uintptr,unsafe.Pointer。
    对于每一种类型,提供了五类原子操作分别是

    • Add, 增加和减少
    • CompareAndSwap, 比较并交换
    • Swap, 交换
    • Load , 读取
    • Store, 存储

    2.Load和Store并发不安全

    Load和Store操作对应与变量的原子性读写,许多变量的读写无法在一个时钟周期内完成,而此时执行可能会被调度到其他线程,无法保证并发安全。
    ⚠️Load 只保证读取的不是正在写入的值,Store只保证写入是原子操作。
    所以在使用的时候要注意。
    下面简单示例:

    package main
    
    import (
        "sync"
        "sync/atomic"
        "fmt"
    )
    
    var (
        wg  sync.WaitGroup
        mu  sync.Mutex
        num int32
    )
    
    func wrap(callback func()) {
        wg.Add(1)
        go func() {
            callback()
            wg.Done()
        }()
    }
    
    // go build -race
    func main() {
        // 1099 、892, 并发不安全
        //wrap(incNumAtomic)
        //wrap(incNumAtomic)
    
        // 1200, 并发安全
        wrap(incNumAtomic2)
        wrap(incNumAtomic2)
    
        wg.Wait()
        fmt.Printf("num=%d\n", num)
    }
    
    func incNumAtomic() {
        for i := 0; i < 600; i++ {
            // atomic.Load*系列函数只能保证读取的不是正在写入的值(比如只被修改了一半的数据)
            // 同样的atomic.Store* 只保证写入是原子操作(保证写入操作的完整性)
            val := atomic.LoadInt32(&num)
            atomic.StoreInt32(&num, val+1)
        }
    }
    
    func incNumAtomic2() {
        for i := 0; i < 600; i++ {
            atomic.AddInt32(&num, 1)
        }
    }
    

    总结

    点击👇查看源码,哈哈哈...

    Github Demo

    相关文章

      网友评论

        本文标题:Go sync/atomic包Load和Store并发不安全

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