Atomic Counters
Use typed sync/atomic operations for independent counter updates and reads across goroutines.
A data race occurs when concurrent goroutines access the same memory location without synchronization and at least one access is a write. A plain counter increment can lose updates because it reads, changes, and writes the value in separate steps. The sync/atomic package provides operations that update a counter as one indivisible operation.
atomic.Int64 is a typed counter available since Go 1.19. Add increments it safely, and Load reads its current value.
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var counter atomic.Int64
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter.Add(1)
}()
}
wg.Wait()
fmt.Println(counter.Load())
}In production
Atomic operations work well for independent counters and flags. They do not make a group of fields change together as one unit. Use a mutex when correctness depends on keeping multiple values consistent, and do not copy a typed atomic after its first use.