下面代碼例子是展現併發下公共數據操做,經過原子函數和互斥鎖怎麼解決。安全
package main import ( "sync" "runtime" "fmt" "sync/atomic" ) var( // counter是全部goroutine都要增長的變量 counter int64 // wg用來等待程序的結束 wg sync.WaitGroup // mutex 用來定義一段代碼臨界區 mutex sync.Mutex ) func main() { // 計數加2,表示要等待兩個goroutine wg.Add(2) // 建立兩個goroutine go incCounter(1) go incCounter(2) // 等待goroutine結束 wg.Wait() fmt.Println("Final Counter:", counter) } // incCounter增長包裏counter變量的值 func incCounter(id int) { // 延時調用,在函數退出時調用Done來通知main函數工做已經完成 defer wg.Done() for count := 0; count < 2; count++ { // 捕獲counter的值 value := counter // 當前goroutine從線程退出,並放回到隊列 runtime.Gosched() // 增長本地value變量的值 value++ // 將該值保存回counter counter = value } } // incCounter增長包裏counter變量的值 func incCounter1(id int) { defer wg.Done() for count := 0; count < 2; count++ { // 安全的對counter加1 atomic.AddInt64(&counter, 1) // 當前goroutine從線程退出,並放回到隊列 runtime.Gosched() } } // incCounter增長包裏counter變量的值 func incCounter2(id int) { // 延時調用,在函數退出時調用Done來通知main函數工做已經完成 defer wg.Done() for count := 0; count < 2; count++ { // 同一時刻只容許一個goroutine進入這個臨界區 mutex.Lock() { // 捕獲counter的值 value := counter // 當前goroutine從線程退出,並放回到隊列 runtime.Gosched() // 增長本地value變量的值 value++ // 將該值保存回counter counter = value } // 釋放鎖,容許其餘正在等待的goroutine進入臨界區 mutex.Unlock() } }