publish atomic counters

This commit is contained in:
Mark McGranaghan 2012-10-19 11:23:09 -04:00
parent 7098c32ade
commit e7cb1d1ac8
4 changed files with 60 additions and 15 deletions

View File

@ -38,8 +38,9 @@ Timers
Tickers
Worker Pools
Rate Limiting
# State Goroutine
# State Mutex
Atomic Counters
# Mutexs
# Stateful Goroutines
Sorting
Sorting by Functions
# Collection Functions

View 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)
}

View File

@ -0,0 +1,4 @@
# Running the program shows that we executed about
# 40,000 operations.
$ go run atomic-counters.go
ops: 40200

View File

@ -1,3 +1,5 @@
// State
package main
import "fmt"
@ -7,14 +9,6 @@ import "sync"
import "sync/atomic"
import "runtime"
func randKey() int {
return rand.Intn(10)
}
func randVal() int {
return rand.Intn(100)
}
// Globally-accessible state.
var data = make(map[int]int)
@ -27,7 +21,7 @@ var opCount int64 = 0
func generateReads() {
total := 0
for {
key := randKey()
key := rand.Intn(10)
dataMutex.Lock()
total += data[key]
dataMutex.Unlock()
@ -39,8 +33,8 @@ func generateReads() {
// Generate random writes.
func generateWrites() {
for {
key := randKey()
val := randVal()
key := rand.Intn(10)
val := rand.Intn(100)
dataMutex.Lock()
data[key] = val
dataMutex.Unlock()
@ -62,5 +56,3 @@ func main() {
finalOpCount := atomic.LoadInt64(&opCount)
fmt.Println(finalOpCount)
}
// todo: "State with Mutexes?"