Go語言中sync.Mutex的使用方法
背景
多個(gè)協(xié)程操作中經(jīng)常出現(xiàn)臟讀寫的情況,這種情況下需要使用互斥鎖,保證在對協(xié)程共享區(qū)域操作的原子性。
如下示例:
啟動了 100個(gè)協(xié)程,每個(gè)協(xié)程累加 100 次,在沒有臟讀寫的情況下,最后結(jié)果應(yīng)該是 100 * 100 = 10000
package main import ( "fmt" "sync" ) func main() { var count = 0 var wg sync.WaitGroup wg.Add(100) for i :=0; i< 100; i++ { go func(){ defer wg.Done() for j := 0; j< 100; j ++ { count ++ } }() } wg.Wait() fmt.Println(count) }
但是實(shí)際結(jié)果一直小于 10000
互斥鎖
count ++ 操作, 分為三個(gè)步驟
在協(xié)程的共享區(qū)域取出 count 當(dāng)前值
當(dāng)前值加一
加一后的值寫回協(xié)程共享區(qū)域
這時(shí)需要使用互斥鎖, 來保證對 count++ 的三個(gè)操作過程中沒有其他協(xié)程進(jìn)行讀寫。
Go的Sync 包提供了Mutex, 讀寫互斥的鎖, 來保證只有一個(gè)協(xié)程對數(shù)據(jù)進(jìn)行讀寫操作。 以保證 count++操作的原子性
如下示例:
package main import ( "fmt" "sync" ) func main() { var count = 0 // 聲明Mutex變量 var mu sync.Mutex var wg sync.WaitGroup wg.Add(100) for i :=0; i< 100; i++ { go func(){ defer wg.Done() for j := 0; j< 100; j ++ { // 添加鎖 mu.Lock() count ++ // 解鎖 mu.Unlock() } }() } wg.Wait() fmt.Println(count) }
在mu.Lock()
和mu.Unlock()
之間的代碼可以保證在操作只會被一個(gè)協(xié)程執(zhí)行。這樣執(zhí)行結(jié)果就是 10000 了
注意
mu.Lock()
和mu.Unlock()
必須成對出現(xiàn),在忘掉 Unlock 的情況下,鎖獲取后永遠(yuǎn)不會得到釋放,其他 的線程/協(xié)程會永遠(yuǎn)處于阻塞狀態(tài),永遠(yuǎn)獲取不到鎖,在忘掉 Lock 的情況下,直接 Unlock 一個(gè)未加鎖的 Mutex,會導(dǎo)致程序 panic。
到此這篇關(guān)于Go語言中sync.Mutex的使用方法的文章就介紹到這了,更多相關(guān)Go sync.Mutex內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang操作MySql數(shù)據(jù)庫的完整步驟記錄
這篇文章主要給大家介紹了關(guān)于Golang操作MySql數(shù)據(jù)庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11goFrame的隊(duì)列g(shù)queue對比channel使用詳解
這篇文章主要為大家介紹了goFrame的gqueue對比channel使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06go Antlr重構(gòu)腳本解釋器實(shí)現(xiàn)示例
這篇文章主要為大家介紹了go Antlr重構(gòu)腳本解釋器實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Golang實(shí)現(xiàn)Redis事務(wù)深入探究
這篇文章主要介紹了Golang實(shí)現(xiàn)Redis事務(wù)深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01