Go語言中管理狀態(tài)的主要機(jī)制是通過通道進(jìn)行通信。在過去的文章中我們已經(jīng)看到了這一點(diǎn),例如工人池。 還有一些其他選項(xiàng)用于管理狀態(tài)。 這里我們將使用sync/atomic
包來實(shí)現(xiàn)由多個(gè)goroutine
訪問的原子計(jì)數(shù)器。
使用一個(gè)無符號(hào)整數(shù)表示計(jì)數(shù)器(正數(shù))。
為了模擬并發(fā)更新,將啟動(dòng)50
個(gè)goroutine
,每個(gè)增量計(jì)數(shù)器大約是1
毫秒。
為了原子地遞增計(jì)數(shù)器,這里使用AddUint64()
函數(shù),在ops
計(jì)數(shù)器的內(nèi)存地址上使用&
語法。
在增量之間等待一秒,允許一些操作累積。
為了安全地使用計(jì)數(shù)器,同時(shí)它仍然被其他goroutine
更新,通過LoadUint64
提取一個(gè)當(dāng)前值的副本到opsFinal
。 如上所述,需要將獲取值的內(nèi)存地址&ops
給這個(gè)函數(shù)。
運(yùn)行程序顯示執(zhí)行了大約40,000
次操作。
所有的示例代碼,都放在
F:\worksp\golang
目錄下。安裝Go編程環(huán)境請(qǐng)參考:http://www.yiibai.com/go/go_environment.html
atomic-counters.go
的完整代碼如下所示 -
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 {
// 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(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)
}
執(zhí)行上面代碼,將得到以下輸出結(jié)果 -
F:\worksp\golang>go run atomic-counters.go
ops: 41360