publish atomic counters
This commit is contained in:
parent
7098c32ade
commit
e7cb1d1ac8
@ -38,8 +38,9 @@ Timers
|
|||||||
Tickers
|
Tickers
|
||||||
Worker Pools
|
Worker Pools
|
||||||
Rate Limiting
|
Rate Limiting
|
||||||
# State Goroutine
|
Atomic Counters
|
||||||
# State Mutex
|
# Mutexs
|
||||||
|
# Stateful Goroutines
|
||||||
Sorting
|
Sorting
|
||||||
Sorting by Functions
|
Sorting by Functions
|
||||||
# Collection Functions
|
# Collection Functions
|
||||||
|
48
examples/atomic-counters/atomic-counters.go
Normal file
48
examples/atomic-counters/atomic-counters.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// The primary mechanism for managing state in Go is
|
||||||
|
// communication over channels. We saw this for example
|
||||||
|
// with [worker pools](worker-pool). There are a few other
|
||||||
|
// options for managing state though. Here we'll
|
||||||
|
// look at using the `sync/atomic` package for simple
|
||||||
|
// counters accessed by multiple goroutines.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "time"
|
||||||
|
import "sync/atomic"
|
||||||
|
|
||||||
|
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 {
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
|
||||||
|
// 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 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` 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)
|
||||||
|
}
|
4
examples/atomic-counters/atomic-counters.sh
Normal file
4
examples/atomic-counters/atomic-counters.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Running the program shows that we executed about
|
||||||
|
# 40,000 operations.
|
||||||
|
$ go run atomic-counters.go
|
||||||
|
ops: 40200
|
@ -1,3 +1,5 @@
|
|||||||
|
// State
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
@ -7,14 +9,6 @@ import "sync"
|
|||||||
import "sync/atomic"
|
import "sync/atomic"
|
||||||
import "runtime"
|
import "runtime"
|
||||||
|
|
||||||
func randKey() int {
|
|
||||||
return rand.Intn(10)
|
|
||||||
}
|
|
||||||
|
|
||||||
func randVal() int {
|
|
||||||
return rand.Intn(100)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Globally-accessible state.
|
// Globally-accessible state.
|
||||||
var data = make(map[int]int)
|
var data = make(map[int]int)
|
||||||
|
|
||||||
@ -27,7 +21,7 @@ var opCount int64 = 0
|
|||||||
func generateReads() {
|
func generateReads() {
|
||||||
total := 0
|
total := 0
|
||||||
for {
|
for {
|
||||||
key := randKey()
|
key := rand.Intn(10)
|
||||||
dataMutex.Lock()
|
dataMutex.Lock()
|
||||||
total += data[key]
|
total += data[key]
|
||||||
dataMutex.Unlock()
|
dataMutex.Unlock()
|
||||||
@ -39,8 +33,8 @@ func generateReads() {
|
|||||||
// Generate random writes.
|
// Generate random writes.
|
||||||
func generateWrites() {
|
func generateWrites() {
|
||||||
for {
|
for {
|
||||||
key := randKey()
|
key := rand.Intn(10)
|
||||||
val := randVal()
|
val := rand.Intn(100)
|
||||||
dataMutex.Lock()
|
dataMutex.Lock()
|
||||||
data[key] = val
|
data[key] = val
|
||||||
dataMutex.Unlock()
|
dataMutex.Unlock()
|
||||||
@ -62,5 +56,3 @@ func main() {
|
|||||||
finalOpCount := atomic.LoadInt64(&opCount)
|
finalOpCount := atomic.LoadInt64(&opCount)
|
||||||
fmt.Println(finalOpCount)
|
fmt.Println(finalOpCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: "State with Mutexes?"
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user