天天看點

golang的同步包sync解析——互斥鎖/讀寫鎖1、臨界資源通路存在的問題2、使用WaitGroup等待一組線程的結束3、互斥鎖——處理臨界資源中的并發問題4、讀寫鎖——多讀一寫

目錄

1、臨界資源通路存在的問題

2、使用WaitGroup等待一組線程的結束

3、互斥鎖——處理臨界資源中的并發問題

4、讀寫鎖——多讀一寫

1、臨界資源通路存在的問題

golang的同步包sync解析——互斥鎖/讀寫鎖1、臨界資源通路存在的問題2、使用WaitGroup等待一組線程的結束3、互斥鎖——處理臨界資源中的并發問題4、讀寫鎖——多讀一寫

如上圖所示,會出現多個視窗賣出同一張票以及賣出負票的問題

2、使用WaitGroup等待一組線程的結束

由于一旦主協程執行結束,即時其他協程還沒有執行完成也會退出,上面例子我們強制在主協程中設定休眠時間,但是這樣做不太好,而使用WaitGroup可以解決上述問題

WaitGroup用于等待一組線程的結束。父線程調用Add方法來設定應等待的線程的數量。每個被等待的線程在結束時應調用Done方法。同時,主線程裡可以調用Wait方法阻塞至所有線程結束。
golang的同步包sync解析——互斥鎖/讀寫鎖1、臨界資源通路存在的問題2、使用WaitGroup等待一組線程的結束3、互斥鎖——處理臨界資源中的并發問題4、讀寫鎖——多讀一寫

如上圖所示,這樣做的話即時主線程執行完了也不會退出,直到等待的線程數量變為0了才會退出

3、互斥鎖——處理臨界資源中的并發問題

保證在任何時候都隻能有一個goroutine來通路資源,其他goroutine都等待

golang的同步包sync解析——互斥鎖/讀寫鎖1、臨界資源通路存在的問題2、使用WaitGroup等待一組線程的結束3、互斥鎖——處理臨界資源中的并發問題4、讀寫鎖——多讀一寫

相對于第一部分的代碼,改進了如下兩個地方:

  • 加入了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 獲得讀鎖定;
  • 同時隻能存在寫鎖定或讀鎖定(讀和寫互斥)。
golang的同步包sync解析——互斥鎖/讀寫鎖1、臨界資源通路存在的問題2、使用WaitGroup等待一組線程的結束3、互斥鎖——處理臨界資源中的并發問題4、讀寫鎖——多讀一寫
golang的同步包sync解析——互斥鎖/讀寫鎖1、臨界資源通路存在的問題2、使用WaitGroup等待一組線程的結束3、互斥鎖——處理臨界資源中的并發問題4、讀寫鎖——多讀一寫