Подтвердить что ты не робот

Являются ли операторы приращения в атоме Go атомом на x86?

Вот какой фон:
Мне нужна переменная счетчика, разделяемая между режимами go, используемая для чего-то вроде просачивающегося ведра. Я знаю, что есть пример просачивающегося потока в Effective Go, параллельный раздел, но число, которое мне нужно отслеживать, может быть очень большим, и я считаю неэффективным использовать количество элементов в канале для его отслеживания. Поэтому я рассматриваю возможность использования общей переменной между различными процедурами для отслеживания числа.

Я понимаю, что без явной конфигурации все подпрограммы go отображаются в один поток. Но если я назначаю более одного потока для программы на многоядерном компьютере, атомы приращения атома? Все ли одинаково для разных типов данных (int32, float32 и т.д.) На разных машинах (x86_32, x86_64, arm)?

Чтобы быть более конкретным, что, если у меня есть counter += 1000 в одной подпрограмме и counter -= 512 в другой процедуре, и две подпрограммы работают в двух потоках? Нужно ли беспокоиться о потокобезопасности? Должен ли я надеть блокировки на counter?

4b9b3361

Ответ 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
}