在x86上,Go语言中的增量操作符是原子的吗?

huangapple go评论82阅读模式
英文:

Are increment operators in Go atomic on x86?

问题

这是一些背景信息:
我需要一个在go协程之间共享的计数器变量,用于类似于漏桶的功能。我知道在Effective Go的并发部分有一个漏桶的例子,但是我需要跟踪的数字可能非常大,使用通道中的元素数量来跟踪可能效率低下。因此,我考虑使用不同协程之间的共享变量来跟踪数字。

我知道在没有显式配置的情况下,所有的go协程都映射到一个线程上。但是,如果我在多核计算机上为程序分配多个线程,递增操作符是原子的吗?对于不同的数据类型(int32float32等)在不同的机器上(x86_32x86_64arm)是否都是一样的?

更具体地说,如果我在一个协程中有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
}

huangapple
  • 本文由 发表于 2012年12月17日 12:04:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/13908129.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定