鍍金池/ 教程/ GO/ Go原子計(jì)數(shù)器實(shí)例
Go panic錯(cuò)誤處理實(shí)例
Go命令行參數(shù)實(shí)例
Go可變參數(shù)的函數(shù)實(shí)例
Go通道同步實(shí)例
Go非阻塞通道操作實(shí)例
Go指針實(shí)例
Go數(shù)字解析實(shí)例
Go語言指針
Go超時(shí)(timeouts)實(shí)例
Go速率限制實(shí)例
Go信號(hào)實(shí)例
Go Base64編碼實(shí)例
Go計(jì)時(shí)器實(shí)例
Go命令行標(biāo)志實(shí)例
Go原子計(jì)數(shù)器實(shí)例
Go語言切片
Go隨機(jī)數(shù)實(shí)例
Go語言類型轉(zhuǎn)換
Go排序?qū)嵗?/span>
Go時(shí)間格式化/解析實(shí)例
Go URL解析實(shí)例
Go字符串函數(shù)實(shí)例
Go語言常量
Go for循環(huán)語句實(shí)例
Go函數(shù)多個(gè)返回值實(shí)例
Go切片實(shí)例
Go行過濾器實(shí)例
Go語言接口
Go語言數(shù)組
Go語言變量
Go字符串格式化實(shí)例
Go斷續(xù)器實(shí)例
Go if/else語句實(shí)例
Go通道緩沖實(shí)例
Go錯(cuò)誤實(shí)例
Go語言映射
Go執(zhí)行過程實(shí)例
Go函數(shù)實(shí)例
Go有狀態(tài)的goroutines實(shí)例
Go按自定義函數(shù)排序?qū)嵗?/span>
Go語言作用域規(guī)則
Go時(shí)代(Epoch)實(shí)例
Go變量實(shí)例
Go互斥體實(shí)例
Go語言范圍(range)
Go程序?qū)嵗?/span>
Go語言入門
Go通道路線實(shí)例
Go閉包(匿名函數(shù))實(shí)例
Go Select實(shí)例
Go通道范圍實(shí)例
Go集合函數(shù)實(shí)例
Hello World程序?qū)嵗?/span>
Go環(huán)境變量實(shí)例
Go語言運(yùn)算符
Go讀取文件實(shí)例
Go延遲(defer)實(shí)例
Go SHA1哈希實(shí)例
Go語言條件和決策
Go語言錯(cuò)誤處理
Go通道實(shí)例
Go指針實(shí)例
Go時(shí)間日期實(shí)例
Go語言字符串
Go語言循環(huán)
Go語言基礎(chǔ)語法
Go語言開發(fā)環(huán)境安裝配置
Go常量實(shí)例
Go語言結(jié)構(gòu)體
Go寫文件實(shí)例
Go正則表達(dá)式實(shí)例
Go JSON實(shí)例
Go語言教程
Go關(guān)閉通道實(shí)例
Go接口實(shí)例
Go語言遞歸
Go switch語句實(shí)例
Go函數(shù)遞歸實(shí)例
Go退出程序?qū)嵗?/span>
Go語言程序結(jié)構(gòu)
Go范圍實(shí)例
Go語言函數(shù)
Go工作池實(shí)例
Go語言數(shù)據(jù)類型

Go原子計(jì)數(shù)器實(shí)例

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