英文:
Are increment operators in Go atomic on x86?
问题
这是一些背景信息:
我需要一个在go协程之间共享的计数器变量,用于类似于漏桶的功能。我知道在Effective Go的并发部分有一个漏桶的例子,但是我需要跟踪的数字可能非常大,使用通道中的元素数量来跟踪可能效率低下。因此,我考虑使用不同协程之间的共享变量来跟踪数字。
我知道在没有显式配置的情况下,所有的go协程都映射到一个线程上。但是,如果我在多核计算机上为程序分配多个线程,递增操作符是原子的吗?对于不同的数据类型(int32
,float32
等)在不同的机器上(x86_32
,x86_64
,arm
)是否都是一样的?
更具体地说,如果我在一个协程中有counter += 1000
,在另一个协程中有counter -= 512
,而这两个协程恰好在两个线程中运行,我需要担心线程安全吗?我需要在counter
上加锁吗?
英文:
Here's some background:
I need a counter variable shared between go routines, used for something like a leaky-bucket. I know there's an example of leaky-bucket in Effective Go, concurrent section, but the number that I need to track may be very large, and I feel it's inefficient to use number of elements in a channel to track it. So I am considering of using a shared variable between different routines to track the number.
I understand that without explicit configuration, all go routines are mapped onto one thread. But if I assign more than one thread to the program on a multi-core computer, is increment operators atomic? Is it all the same for different data types (int32
, float32
, etc.) on different machines (x86_32
, x86_64
, arm
)?
To be more concrete, What if I have counter += 1000
in one routine, and counter -= 512
in another routine, and the two routines happens to be running in two threads? Do I need to worry about thread-safty? Shall I put on locks on the counter
?
答案1
得分: 25
不,增量操作不应该被假设为原子操作。请使用原子加法函数或互斥锁。
假设如下:
import "sync/atomic"
var counter = new(int32)
一个goroutine可以执行atomic.AddInt32(counter, 1000)
,而另一个goroutine可以执行atomic.AddInt32(counter, -512)
,而不使用互斥锁。
如果你更愿意使用互斥锁:
import "sync"
var counter int32
var mutex sync.Mutex
func Add(x int32) {
mutex.Lock()
defer mutex.Unlock()
counter += x
}
英文:
No, increment should never be assumed to be atomic. Use the atomic addition functions or a mutex.
Lets assume:
import "sync/atomic"
var counter = new(int32)
One goroutine could do atomic.AddInt32(counter, 1000)
while another did atomic.AddInt32(counter, -512)
without a mutex.
If you would rather use a mutex:
import "sync"
var counter int32
var mutex sync.Mutex
func Add(x int32) {
mutex.Lock()
defer mutex.Unlock()
counter += x
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论