-
Notifications
You must be signed in to change notification settings - Fork 26
/
atomic-counter.go
43 lines (35 loc) · 1.34 KB
/
atomic-counter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main
// 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 sync/atomic package for atomic counters accessed by multiple goroutines.
import (
"fmt"
"sync/atomic"
"time"
)
// AtomicCounter illustrate sync/atomic package usecase.
func AtomicCounter() {
// We’ll use an unsigned integer to represent our (always-positive) counter.
var ops uint64
// 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 AddUint64,
// giving it the memory address of our ops counter with the & syntax.
atomic.AddUint64(&ops, 1)
// Wait a bit between increments.
time.Sleep(time.Millisecond)
}
}()
}
// Wait a second to allow some ops to accumulate.
time.Sleep(5 * 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 via LoadUint64.
// As above we need to give this function the memory address &ops from which to fetch the value.
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
}