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
?
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
}