concurrency - Go 中的增量运算符在 x86 上是原子的吗?

标签 concurrency thread-safety go atomic

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

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

更具体地说,如果我有 counter += 1000 在一个例程中,而 counter -= 512 在另一个例程中,并且这两个例程恰好是在两个线程中运行?我需要担心线程安全吗?我应该在柜台上锁吗?

最佳答案

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

假设:

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
}

关于concurrency - Go 中的增量运算符在 x86 上是原子的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13908129/

相关文章:

go - vim-go 找不到需要的库

go - 在 Go 中列出目录

google-app-engine - 如何忽略 datastore.Query.GetAll() 中的错误?

jakarta-ee - 如果有异步方法仍在运行,无状态 session 是否会被另一个线程使用?

java - 与 ThreadLocal 同步还是 InheritableThreadLocal?

java - 使用 ExecutorService 并行化循环来执行任务

java - 以线程安全的方式发布非线程安全的对象字段

Java多线程同步块(synchronized block)永远循环

javascript - 使用 mongoose 中间件删除依赖文档时的并发问题

qt - Qt 中的 connect() 调用线程安全吗?