目錄
1、臨界資源通路存在的問題
2、使用WaitGroup等待一組線程的結束
3、互斥鎖——處理臨界資源中的并發問題
4、讀寫鎖——多讀一寫
1、臨界資源通路存在的問題
如上圖所示,會出現多個視窗賣出同一張票以及賣出負票的問題
2、使用WaitGroup等待一組線程的結束
由于一旦主協程執行結束,即時其他協程還沒有執行完成也會退出,上面例子我們強制在主協程中設定休眠時間,但是這樣做不太好,而使用WaitGroup可以解決上述問題
WaitGroup用于等待一組線程的結束。父線程調用Add方法來設定應等待的線程的數量。每個被等待的線程在結束時應調用Done方法。同時,主線程裡可以調用Wait方法阻塞至所有線程結束。
如上圖所示,這樣做的話即時主線程執行完了也不會退出,直到等待的線程數量變為0了才會退出
3、互斥鎖——處理臨界資源中的并發問題
保證在任何時候都隻能有一個goroutine來通路資源,其他goroutine都等待
相對于第一部分的代碼,改進了如下兩個地方:
- 加入了sync.Mutex互斥鎖,解決了臨界資源并發通路的問題
- 加入了sync.WaitGroup,解決了主協程一結束其他子協程就被強制結束的問題
4、讀寫鎖——多讀一寫
RWMutex是讀寫互斥鎖。該鎖可以被同時多個讀取者持有或唯一個寫入者持有。RWMutex可以建立為其他結構體的字段;零值為解鎖狀态。RWMutex類型的鎖也和線程無關,可以由不同的線程加讀取鎖/寫入和解讀取鎖/寫入鎖。
讀寫鎖有如下四個方法:
- 寫操作的鎖定和解鎖分别是
和func (*RWMutex) Lock
;func (*RWMutex) Unlock
- 讀操作的鎖定和解鎖分别是
和func (*RWMutex) Rlock
。func (*RWMutex) RUnlock
讀寫鎖的差別在于:
- 當有一個 goroutine 獲得寫鎖定,其它無論是讀鎖定還是寫鎖定都将阻塞直到寫解鎖;
- 當有一個 goroutine 獲得讀鎖定,其它讀鎖定仍然可以繼續;
- 當有一個或任意多個讀鎖定,寫鎖定将等待所有讀鎖定解鎖之後才能夠進行寫鎖定。
是以說這裡的讀鎖定(RLock)目的其實是告訴寫鎖定,有很多協程或者程序正在讀取資料,寫操作需要等它們讀(讀解鎖)完才能進行寫(寫鎖定)。
我們可以将其總結為如下三條:
- 同時隻能有一個 goroutine 能夠獲得寫鎖定;
- 同時可以有任意多個 gorouinte 獲得讀鎖定;
- 同時隻能存在寫鎖定或讀鎖定(讀和寫互斥)。