The primary mechanism for managing state in Go is
communication over channels. We saw this for example
with worker pools. There are a few other
options for managing state though. Here we’ll
look at using the |
|
package main
|
|
import "fmt"
import "time"
import "sync/atomic"
import "runtime"
|
|
func main() {
|
|
We’ll use an unsigned integer to represent our (always-positive) counter. |
var ops uint64 = 0
|
To simulate concurrent updates, we’ll start 50 goroutines that each increment the counter about once a millisecond. |
for i := 0; i < 50; i++ {
go func() {
for {
|
To atomically increment the counter we
use |
atomic.AddUint64(&ops, 1)
|
Allow other goroutines to proceed. |
runtime.Gosched()
}
}()
}
|
Wait a second to allow some ops to accumulate. |
time.Sleep(time.Second)
|
In order to safely use the counter while it’s still
being updated by other goroutines, we extract a
copy of the current value into |
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
}
|
Running the program shows that we executed about 40,000 operations. |
$ go run atomic-counters.go
ops: 40200
|
Next we’ll look at mutexes, another tool for managing state. |
Previous example: Rate Limiting.
Next example: Mutexes.