中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang中鎖的使用場景主要涉及到哪些呢

發布時間:2022-01-04 17:17:24 來源:億速云 閱讀:121 作者:柒染 欄目:大數據

golang中鎖的使用場景主要涉及到哪些呢,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

一、什么場景下需要用到鎖

當程序中就一個線程的時候,是不需要加鎖的,但是通常實際的代碼不會只是單線程,有可能是多個線程同時訪問公共資源,所以這個時候就需要用到鎖了,那么關于鎖的使用場景主要涉及到哪些呢?

1. 多個線程在讀相同的數據時
2. 多個線程在寫相同的數據時
3. 同一個資源,有讀又有寫時

二、Go 鎖分為兩種:

  • 互斥鎖 (sync.Mutex)

  • 讀寫鎖 (sync.RWMutex 底層依賴Mutex實現  )

互斥鎖是并發程序對公共資源訪問限制最常見的方式。在Go中,sync.Mutex 提供了互斥鎖的實現。

當一個goroutine獲得了Mutex后,其他goroutine只能等待,除非該goroutine釋放這個Mutex。

互斥鎖結構:

type Mutex struct {    state int32    sema  uint32}

1. 鎖定狀態值為1,未鎖定狀態鎖為 0 。

2. Lock()加鎖、Unlock解鎖。

讀寫鎖則是對讀寫操作進行加鎖。需要注意的是多個讀操作之間不存在互斥關系,這樣提高了對共享資源的訪問效率。

Go中讀寫鎖由 sync.RWMutex 提供,RWMutex在讀鎖占用的情況下,會阻止寫,但不阻止讀。RWMutex在寫鎖占用情況下,會阻止任何其他goroutine(無論讀和寫)進來,整個鎖相當于由該goroutine獨占。

讀寫鎖結構:

type RWMutex struct {    w           Mutex  // held if there are pending writers    writerSem   uint32 // semaphore for writers to wait for completing readers    readerSem   uint32 // semaphore for readers to wait for completing writers    readerCount int32  // number of pending readers    readerWait  int32  // number of departing readers}

1. RWMutex是單寫多讀鎖,該鎖可以加多個讀鎖或者一個寫鎖。

2. 讀鎖占用的情況會阻止寫,不會阻止讀,多個goroutine可以同時獲取讀鎖。

3. 寫鎖會阻止其他gorotine不論讀或者寫進來,整個鎖由寫鎖goroutine占用 與第一條共用示范代碼

4. 適用于讀多寫少的場景


三、如何使用互斥鎖

Mutex為互斥鎖,Lock() 加鎖,Unlock() 解鎖,使用Lock() 加鎖后,便不能再次對其進行加鎖,直到利用Unlock()解鎖對其解鎖后,才能再次加鎖.適用于讀寫不確定場景,即讀寫次數沒有明顯的區別,并且只允許只有一個讀或者寫的場景,所以該鎖葉叫做全局鎖。

互斥鎖只能鎖定一次,當在解鎖之前再次進行加鎖,便會無法加鎖。如果在加鎖前解鎖,便會報錯"panic: sync: unlock of unlocked mutex"。 

package mainimport ("fmt"    "sync")
var (    count int    lock sync.Mutex)
func main() {    for i := 0; i < 2; i++ {        go func() {            for i := 1000000; i > 0; i-- {                lock.Lock()                count ++                lock.Unlock()            }            fmt.Println(count)        }()    }
   fmt.Scanf("\n") //等待子線程全部結束}
運行結果:19525332000000 //最后的線程打印輸出

對于上面的程序,a作為一個公共的資源,所以對a的改變、讀寫等操作都需要加鎖。

需要注意的問題:

  1. 不要重復鎖定互斥鎖
  2. 不要忘記解鎖互斥鎖,必要時使用 defer 語句
  3. 不要在多個函數之間直接傳遞互斥鎖

四、如何使用讀寫鎖

讀寫鎖的場景主要是在多線程的安全操作下,并且讀的情況多于寫的情況,也就是說既滿足多線程操作的安全性,也要確保性能不能太差,這時候,我們可以考慮使用讀寫鎖。當然你也可以簡單暴力直接使用互斥鎖(Mutex)。

Lock() 寫鎖,如果在添加寫鎖之前已經有其他的讀鎖和寫鎖,則lock就會阻塞直到該鎖可用,為確保該鎖最終可用,已阻塞的 Lock 調用會從獲得的鎖中排除新的讀取器,即寫鎖權限高于讀鎖,有寫鎖時優先進行寫鎖定。

Unlock() 寫鎖解鎖,如果沒有進行寫鎖定,則就會引起一個運行時錯誤。

RLock() 讀鎖,當有寫鎖時,無法加載讀鎖,當只有讀鎖或者沒有鎖時,可以加載讀鎖,讀鎖可以加載多個,所以適用于"讀多寫少"的場景。

RUnlock() 讀鎖解鎖,RUnlock 撤銷單次RLock 調用,它對于其它同時存在的讀取器則沒有效果。若 rw 并沒有為讀取而鎖定,調用 RUnlock 就會引發一個運行時錯誤。

package mainimport ("fmt"    "sync")
var (    count int    rwLock sync.RWMutex)
func main() {    for i := 0; i < 2; i++ {        go func() {            for i := 1000000; i > 0; i-- {                rwLock.Lock()                count ++                rwLock.Unlock()            }            fmt.Println(count)        }()    }
   fmt.Scanf("\n") //等待子線程全部結束}
運行結果:19686372000000

看著挺復雜的,其實簡單來說就是:

  1. 讀鎖不能阻塞讀鎖

  2. 讀鎖需要阻塞寫鎖,直到所有讀鎖都釋放

  3. 寫鎖需要阻塞讀鎖,直到所有寫鎖都釋放

  4. 寫鎖需要阻塞寫鎖

關于golang中鎖的使用場景主要涉及到哪些呢問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金乡县| 保定市| 丹江口市| 韩城市| 社会| 泸西县| 长汀县| 永和县| 曲靖市| 福建省| 赤水市| 江源县| 阳春市| 江口县| 布尔津县| 鄄城县| 巴东县| 仁怀市| 洛扎县| 南宫市| 开鲁县| 大宁县| 通榆县| 东山县| 吉林市| 车险| 保亭| 丰都县| 东平县| 二连浩特市| 新津县| 莲花县| 新巴尔虎右旗| 聂拉木县| 平原县| 镇坪县| 扶沟县| 陕西省| 石城县| 巫溪县| 贵州省|