golang線程安全與互斥鎖


在高並發下或多goroutine同時執行下,可能會同時讀寫同一塊內存

 

Golang樂觀鎖和悲觀鎖

修改一個數值的步驟:

  ①把想修改的數值從某個地方取出來

  ②在取出來的數值修改為期望值

  ③把修改后的數值保存到原來的地方

 

可能存在的問題:

  如果兩個goroutine同時執行修改數值的步驟,都要進行第③步了,這么看下來,先執行第③步的goroutine做了白功,因為后面那個goroutine緊接着就把這個值覆蓋了

 

悲觀鎖認為:

  每次修改變量的值的時候總會遇到並發,一定會存在其他goroutine也在修改這個變量的值。為了防止此類情況發生,一定要嚴格執行 ①先上鎖 ②執行修改的3個步驟 ③解鎖,以保證數據的精確。

  悲觀鎖有互斥鎖和讀寫鎖

樂觀鎖認為:

  每次修改變量值的時候不會遇到並發這么倒霉的事,所以3個步驟中直接不上鎖走完①②步,到了要執行第③步的時候,檢查一下這個數值是否改變,如果沒有,則執行第③步;如果被已經被別的goroutine修改了,那么重新執行①②③。整個環節不存在加鎖和解鎖的操作

 

 

悲觀鎖】互斥鎖 & 讀寫鎖

互斥鎖:任何一個goroutine讀或者寫,其他goroutine都只能等待。適用於讀寫相當的場景

讀寫鎖:只要沒有goroutine寫,可以有多個goroutine一起讀。一旦有一個goroutine要開始寫,其他goroutine都不能讀和寫。適用於讀多寫少的場景

看起來讀寫鎖效率要高一些,但一般情況下卻是互斥鎖更加高效?讀寫鎖的底層實現是互斥鎖+計數器,只有在鎖住的時候業務耗時過長,讀寫沖突更嚴重的時候,讀寫鎖才有優勢

參考文章:https://blog.csdn.net/myz123321/article/details/89048002,我沒試過。

 

【atomic原子操作】

原子操作是指不會被線程調度機制打斷的操作;原子操作一旦開始,就一直運行到結束,中間不會有任何 context switch(上下文切換,從當前線程切換到另一個線程)。(from 百度百科)

對於編程語言中變量的修改,可以認為原子操作需滿足下面的條件:① 變量的讀寫過程不可中斷(不可以讀到一半做其他事情,也不可寫到一半做其他事情),② 變量的讀寫過程不可同時進行(不可以寫變量的同時讀取變量,防止讀取到僅更新了一半的變量值;也不可以寫變量的同時另一個線程也在寫這個變量,防止其中一個更新無效)。

import "sync/atomic"

atomic.AddInt64(&p, 1000)
atomic.LoadInt64(&p, 1000)

可惜只能對數值進行操作

參考文章:https://jingwei.link/2019/05/11/golang-concurrency-02.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM