【问题标题】:Are increment operators in Go atomic on x86?Go 中的增量运算符在 x86 上是原子的吗?
【发布时间】:2012-12-04 04:37:46
【问题描述】:

这里有一些背景:
我需要一个在 go 例程之间共享的计数器变量,用于类似漏桶的东西。我知道在 Effective Go,concurrent 部分有一个leaky-bucket 的例子,但是我需要跟踪的数量可能非常大,我觉得使用通道中的元素数量来跟踪它是低效的。所以我正在考虑在不同例程之间使用共享变量来跟踪数字。

我知道如果没有明确的配置,所有的 goroutine 都会映射到一个线程上。但是如果我在多核计算机上为程序分配多个线程,增量运算符是原子的吗?不同机器(x86_32x86_64arm)上的不同数据类型(int32float32等)是否都一样?

更具体地说,如果我在一个例程中有counter += 1000,在另一个例程中有counter -= 512,而这两个例程恰好在两个线程中运行,该怎么办?我需要担心线程安全吗?要不要给counter加锁?

【问题讨论】:

    标签: concurrency thread-safety go atomic


    【解决方案1】:

    不,增量不应该被认为是原子的。使用原子加法函数或互斥体。

    假设:

    import "sync/atomic"
    var counter = new(int32)
    

    一个 goroutine 可以在没有互斥体的情况下执行 atomic.AddInt32(counter, 1000) 而另一个执行 atomic.AddInt32(counter, -512)

    如果您更愿意使用互斥锁:

    import "sync"
    var counter int32
    var mutex sync.Mutex
    
    func Add(x int32) {
        mutex.Lock()
        defer mutex.Unlock()
        counter += x
    }
    

    【讨论】:

    • 哇。谢谢!我没有注意到有sync/atomic。这让事情变得容易多了!
    猜你喜欢
    • 2019-05-18
    • 2017-06-14
    • 2011-11-30
    • 1970-01-01
    • 2012-05-17
    • 2014-02-22
    • 2012-05-18
    • 2015-05-19
    • 1970-01-01
    相关资源
    最近更新 更多