競態,就是多個協程同時訪問臨界區,由併發而產生的數據不一樣步的狀態。併發
這個說的有點low,沒辦法,我就是這麼表達的,官方的請度娘。工具
先上代碼:3d
輸出:協程
爲什麼不是1000?就是由於競態,發生競態後,最終的輸出是以最後一個協程執行的結果爲準,但最後一個協程有必定的隨機性,不是先跑先完。blog
改一下代碼:隊列
輸出:同步
由於加了鎖,這1000個協程是按照隊列的順序執行12行,因此穩定輸出 final value of x 1000引用
再看:im
輸出:d3
照樣穩定輸出 final value of x 1000,由於信道的讀和寫都具備排他性,雖然不是鎖住臨界區,可是能起到讓後來的協程排隊的效果。
那麼這兩種狀況怎麼選擇呢? 引用一個大牛的話:
經過使用 Mutex 和信道,咱們已經解決了競態條件的問題。那麼咱們該選擇使用哪個?答案取決於你想要解決的問題。若是你想要解決的問題更適用於 Mutex,那麼就用 Mutex。若是須要使用 Mutex,無須猶豫。而若是該問題更適用於信道,那就使用信道。:)
因爲信道是 Go 語言很酷的特性,大多數 Go 新手處理每一個併發問題時,使用的都是信道。這是不對的。Go 給了你選擇 Mutex 和信道的餘地,選擇其中之一均可以是正確的。
整體說來,當 Go 協程須要與其餘協程通訊時,可使用信道。而當只容許一個協程訪問臨界區時,可使用 Mutex。
就咱們上面解決的問題而言,我更傾向於使用 Mutex,由於該問題並不須要協程間的通訊。因此 Mutex 是很天然的選擇。
個人建議是去選擇針對問題的工具,而別讓問題去將就工具。:)