Здесь у нас есть ход, предоставленный Go by Example
для объяснения атомарного пакета.
https://gobyexample.com/atomic-counters
package main
import "fmt"
import "time"
import "sync/atomic"
func main() {
var ops uint64
for i := 0; i < 50; i++ {
go func() {
for {
atomic.AddUint64(&ops, 1)
time.Sleep(time.Millisecond)
}
}()
}
time.Sleep(time.Second)
opsFinal := atomic.LoadUint64(&ops) // Can I replace it?
fmt.Println("ops:", opsFinal)
}
Для atomic.AddUnit64
это просто понять.
Вопрос1
Что касается операции read
, почему необходимо использовать atomic.LoadUnit
, а не читать этот счетчик напрямую?
Вопрос2
МожетЯ заменяю последние две строки на следующие строки?
До
opsFinal := atomic.LoadUint64(&ops) // Can I replace it?
fmt.Println("ops:", opsFinal)
После
opsFinal := ops
fmt.Println("ops:", opsFinal)
Вопрос3
Обеспокоены ли мы этим сценарием?
- CPU загружает данные из памяти
- CPU манипулирует данными
- Записывает данные обратно в память.Несмотря на то, что этот шаг быстрый, но он все же требует времени.
Когда процессор выполняет шаг 3, другая процедура может считывать неполные и грязные данные из памяти.Так что использование atomic.LoadUint64
могло бы избежать проблем такого рода?
Ссылка
Доступны ли операции чтения и записи для uint8 в golang atomic?