《Java後端知識體系》系列之併發編程基礎(三)鎖的概述(悲觀鎖、樂觀鎖、公平鎖、非公平鎖、獨佔鎖、共享鎖、自旋鎖)

最近深究併發編程的文章,看一點總結一點,也不算總結,就是把自己覺得有用的抄下來,對幾個月後的面試希望有幫助!!

鎖的概述

  • 悲觀鎖與樂觀鎖

    • 悲觀鎖:悲觀鎖是數據對外界的修改保持保守的態度,認爲數據會被其它線程修改,所以每次對數據做處理時都會加鎖,並且處理數據過程中數據也處於鎖定狀態。
      • 實現方法:Java中的synchronized鎖以及lock鎖都是悲觀鎖。
    • 樂觀鎖:樂觀鎖相對於悲觀鎖來說,認爲數據在一般情況下並不會造成衝突,所以訪問數據時並不會加入排他鎖,而是在數據提交更新時,纔會對驗證數據是否衝突。
      • 實現方法:樂觀鎖的實現方式有CAS,以及版本控制(添加version字段來控制更新次數)
  • 公平鎖與非公平鎖

    • 公平鎖:公平鎖時指線程獲取鎖的順序是按照線程請求鎖的順序來執行的,也就是先請求鎖的線程先獲得鎖
      • 實現方法:ReentrantLock提供了公平鎖,實現方式爲ReentrantLock lock = new ReentrantLock(true)
    • 非公平鎖:非公平鎖是在運行時進行競爭,誰競爭到鎖就是誰的,也就是先來不一定先得。
      • 實現方法:ReentrantLock也提供了非公平鎖的實現方式,ReentrantLock lock = new ReentrantLock(false)。如果構造函數不傳遞參數,默認是非公平鎖。synchronized也是非公平鎖,當線程釋放鎖時,處於就緒態的線程會競爭獲得鎖(自旋的方式)。
    • 總結:沒有公平性需求的前提下儘量使用非公平鎖,因爲公平鎖會帶來性能開銷。
  • 獨佔鎖與共享鎖

    • 獨佔鎖:獨佔鎖是任何時候都只有一個線程可以得到鎖,獨佔鎖是一種悲觀鎖,每次訪問資源都會先加上互斥鎖,這樣限制了併發性,因爲讀操作並不會影響數據的一致性,而獨佔鎖同一時刻由一個線程讀取數據,其它線程必須等待當前線程釋放鎖之後才能進行讀取。
      • 實現方式:ReentrantLock是獨佔鎖,synchronized也是獨佔鎖。
    • 共享鎖:共享鎖是可以由多個線程持有。共享鎖其實是一種樂觀鎖,放寬了加鎖的條件,允許多個線程同時操作。
      • 實現方式:ReadWriteLock讀寫鎖是共享鎖,它允許一個資源可以被多個線程同時進行讀操作。
  • 可重入鎖

    • 概念:如果一個線程獲得了鎖,那麼這個線程就可以無限次數的進入被該鎖鎖住的代碼。

      public class Hello {
          public synchronized void helloA(){
              System.out.println("hello");
          }
      
      
          public synchronized void helloB(){
              System.out.println("hello B");
              helloA();
          }
      }
      
    • 以上代碼中,調用helloB方法會提前獲取內置鎖,然後打印輸出,之後調用helloA方法,在調用前會先獲取內置鎖,如果內置鎖不是可重入的,那麼調用線程會一直被阻塞。

    • synchronized內部鎖是可重入鎖,可重入鎖的原理就是在內部維護一個線程標識,用來標識該鎖被哪個線程佔用,然後關聯一個計數器,一開始計數器爲0,說明該鎖沒有被其它線程佔用,當一個線程獲取了該鎖時,計數器加1,這時其它線程再來獲取鎖時就會發現鎖的持有者不是自己而被阻塞掛起。但是當獲取了該鎖的線程再次獲取鎖時發現鎖的擁有者是自己,計數器會繼續加1,當釋放鎖後計數器減1,當計數器爲0時,鎖裏面的線程標識被重置爲null,這時候其它被阻塞的線程會喚醒來競爭鎖。

  • 自旋鎖

    • 概念: Java中一個線程獲取鎖失敗後會被切換到內核狀態被掛起,當該線程獲取到鎖之後又需要從內核態切換爲用戶態而喚醒該線程,而從用戶態切換到內核態開銷是很大的,在一定程度上影響併發性能。自旋鎖是當線程獲取鎖時,如果發現鎖已經被其它線程佔用,它不馬上阻塞自己,在不放棄CPU使用權的情況下,多次嘗試獲取鎖(默認次數爲10,可以使用-XX:PreBlockSpinsh參數設置),很有可能後面幾次嘗試中其它線程已經釋放了鎖,如果嘗試指定次數仍然沒有獲取到鎖,則當前線程會被阻塞掛起
    • 實現方式:synchronized中就有通過自旋鎖來實現競爭鎖的情況。

我是會敲代碼的湯姆貓!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章