各類鎖(互斥鎖,自旋鎖,讀寫鎖,樂觀鎖,悲觀鎖,死鎖)


互斥鎖

當有一個線程要訪問共享資源(臨界資源)之前會對線程訪問的這段代碼(臨界區)進行加鎖。如果在加鎖之后沒釋放鎖之前其他線程要對臨界資源進行訪問,則這些線程會被阻塞睡眠,直到解鎖,如果解鎖時有一個或者多個線程阻塞,那么這些鎖上的線程就會變成就緒狀態,然后第一個變為就緒狀態的線程就會獲取資源的使用權,並且再次加鎖,其他線程繼續阻塞等待。

讀寫鎖

也叫做共享互斥鎖,讀模式共享,寫模式互斥。有點像數據庫負載均衡的讀寫分離模式。它有三種模式:讀加鎖狀態,寫加鎖狀態和不加鎖狀態。簡單來說就是只有一個線程可以占有寫模式的讀寫鎖,但是可以有多個線程占用讀模式的讀寫鎖。
當寫加鎖的模式下,任何線程對其進行加鎖操作都會被阻塞,直到解鎖。
當在讀加鎖的模式下,任何線程都可以對其進行讀加鎖的操作,但所有試圖進行寫加鎖操作的線程都會被阻塞。直到所有讀線程解鎖。但是當讀線程太多時,寫線程一直被阻塞顯然是不對的,所以一個線程想要對其進行寫加鎖時,就會阻塞讀加鎖,先讓寫加鎖線程加鎖

自旋鎖

自旋鎖和互斥鎖很像,唯一不同的是自旋鎖訪問加鎖資源時,會一直循環的查看是否釋放鎖。這樣要比互斥鎖效率高很多,但是只會占用CPU。所以自旋鎖適用於多核的CPU。但是還有一個問題是當自旋鎖遞歸調用的時候會造成死鎖現象。所以慎重使用自旋鎖。

樂觀鎖

這其實是一種思想,當線程去拿數據的時候,認為別的線程不會修改數據,就不上鎖,但是在更新數據的時候會去判斷以下其他線程是否修改了數據。通過版本來判斷,如果數據被修改了就拒絕更新,之所以叫樂觀鎖是因為並沒有加鎖。

樂觀鎖的實現機制CAS

CAS理解類似於事務:全稱Compare And Swap(比較與交換),解決多線程並行情況下使用鎖造成性能損耗的一種機制。

處理器 CAS 指令(內存地址V, 舊值, 新值)

CAS的原理:

利用現代處理器都支持的CAS的指令,循環這個指令,直到成功為止.

CAS原理流程圖如下:

 

CAS相關的問題:

  • ABA問題:在樂觀鎖期間,另一個線程修改old value值為new value值,然后又把new value值重新修改為old value.
    • ABA解決方案:加版本號
      • AtomicMarkableReference 可以解決,使用boolean變量——表示引用變量是否被更改過,不關心中間變量變化了幾次
      • AtomicStampedReference 也可以解決,其中的構造方法中initialStamp(時間戳)用來唯一標識引用變量,引用變量中途被更改了幾次
  • 開銷問題:CAS在一直拿不到鎖時會一直循環,耗費CPU,造成資源上的浪費
  • 只能保證一個共享變量的原子操作:在內存中 get() 變量時,只能get出一個變量
    • 取巧解決方案:把兩個變量封裝成一個 

悲觀鎖

當線程去哪數據的時候,總以為別的線程會去修改數據,所以它每次拿數據的時候都會上鎖,別的線程去拿數據的時候就會阻塞。
這兩種鎖一般用於數據庫,當一個數據庫的讀操作遠遠大於寫的操作次數時,使用樂觀鎖會加大數據庫的吞吐量。


免責聲明!

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



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