51 lines
2.0 KiB
Go
51 lines
2.0 KiB
Go
// Основным механизмом управления состоянием в Go является
|
||
// связь по каналам. Мы видели это, например, с [пулами воркеров](worker-pools).
|
||
// Есть несколько других вариантов управления состоянием.
|
||
// Здесь мы рассмотрим использование пакета `sync/atomic`
|
||
// для _атомарных счетчиков_, к которым обращаются горутины.
|
||
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"sync"
|
||
"sync/atomic"
|
||
)
|
||
|
||
func main() {
|
||
|
||
// Мы будем использовать целое число без знака
|
||
// для представления нашего (всегда положительного)
|
||
// счетчика.
|
||
var ops uint64
|
||
|
||
// WaitGroup поможет нам подождать, пока все горутины
|
||
// завершат свою работу.
|
||
var wg sync.WaitGroup
|
||
|
||
// Мы запустим 50 горутин, каждая из которых увеличивает
|
||
// счетчик ровно в 1000 раз.
|
||
for i := 0; i < 50; i++ {
|
||
wg.Add(1)
|
||
|
||
go func() {
|
||
for c := 0; c < 1000; c++ {
|
||
// Для атомарного увеличения счетчика мы
|
||
// используем AddUint64, присваивая ему адрес
|
||
// памяти нашего счетчика `ops` с префиксом `&`.
|
||
atomic.AddUint64(&ops, 1)
|
||
}
|
||
wg.Done()
|
||
}()
|
||
}
|
||
|
||
// Ждем пока завершатся горутины.
|
||
wg.Wait()
|
||
|
||
// Теперь доступ к `ops` безопасен, потому что мы знаем,
|
||
// что никакие другие горутины не пишут в него. Безопасное
|
||
// чтение атомарного счетчика во время его обновления также
|
||
// возможно, используя функцию `atomic.LoadUint64`.
|
||
fmt.Println("ops:", ops)
|
||
}
|