一文徹底搞懂面試中常問的各種“鎖”

深夜裡的程式猿發表於2019-04-02

前言

鎖,顧名思義就是鎖住一些資源,當只有我們拿到鑰匙的時候,才能操作鎖住的資源。在我們的Java,資料庫,還有一些分散式的環境中,總是充斥著各種各樣的鎖讓人頭疼,例如“公平鎖”、“自旋鎖”、“讀寫鎖”、“分散式鎖”等等。

其實真實的情況是,鎖並沒有那麼多,很多概念只是從不同的功能特性,設計,以及鎖的狀態這些不同的側重點來說明的,因此我們可以根據不同的分類來搞明白為什麼會有這些“鎖”?坐穩扶好了,準備開車。

正文

“公平鎖”與“非公平鎖”

公平鎖:指執行緒在等待獲取同一個鎖的時候,是嚴格按照申請鎖的時間順序來進行的,這就意味著在程式正常運作的時候,不會有執行緒執行不到,而被“餓死”,但是也需要額外的機制來維護這種順序,所以效率相對於非公平鎖會差點。

非公平鎖:概念跟“公平鎖”恰恰相反,隨機執行緒獲取鎖,相率相對高。

new ReentrantLock(); //預設非公平鎖
new ReentrantLock(true); //公平鎖
複製程式碼

“重入鎖(遞迴鎖)”與“不可重入鎖(自旋鎖)”

這裡要注意了,重入/遞迴,不可重入/自旋,雖然名字不同,但是確實是同一種鎖,只是從鎖的表現跟實現方式的角度來命名而已。

重入鎖:當一個執行緒獲取了A鎖以後,若後續方法執行被A鎖鎖住的話,當前執行緒也是可以直接進入的。

public class Demo {
  private Lock lockA;
 
  public Demo(Lock Lock) {
    this.lockA = lock;
  }
 
  public void methodA() {
    lockA.lock();
    methodB();
    lockA.unlock();
  }
 
  public void methodB() {
    lockA.lock();
    //dosm
    lockA.unlock();
  }
  
  }
複製程式碼

當我們執行methodA()的時候,執行緒獲取了lockA,然後呼叫methodB()的時候發現也需要lockA,由於這是一個可重入鎖,所以當前執行緒也是可以直接進入的。在java中,synchronized跟ReetrantLock都是可重入鎖。

不可重入鎖:以上面的程式碼例項來說明,就是methodA進入methodB的時候不能直接獲取鎖,必須先呼叫unLock釋放鎖。才能執行下去,那實現不可重入鎖有什麼方式呢?那就是自旋,所以會有一個小名叫做自旋鎖。

public class SpinLock {

  private AtomicReference<Thread> sign =new AtomicReference<>();

  public void lock(){
    Thread current = Thread.currentThread();
    while(!sign .compareAndSet(null, current)){
    }
  }

  public void unlock (){
    Thread current = Thread.currentThread();
    sign .compareAndSet(current, null);
  }
}
複製程式碼

“悲觀鎖”與“樂觀鎖”

這兩種鎖呢,其實是一個很巨集觀的分類,它不是一種具體的鎖,而是泛指看待併發的程度。

悲觀鎖:有一個“悲觀”的心態,既每次取資料的時候,都會認為該資料會被修改,所以必須加一把鎖才安心。

樂觀鎖:樂觀的孩子,認為同一個資料不會發生併發操作的行為,所以取的時候不會加鎖,只有在更新的時候,會通過例如版本號之類的來判斷是否資料被修改了。

Java中各種鎖其實都是悲觀鎖的實現,既操作的資料的都會被獲取鎖的執行緒鎖住,而樂觀鎖的話,一般是通過cas(compare and swap)的思想來實現,例如一些原子類AtomicInteger使用自旋來原子更新。

“共享鎖”與“排他鎖”

這兩種鎖的概念比較多的出現在資料庫的事務當中。

共享鎖:也稱讀鎖或S鎖。如果事務對資料A加上共享鎖後,則其他事務只能對A再加共享鎖,不能加排它鎖。獲准共享鎖的事務只能讀資料,不能修改資料。在java中的ReetrantReadWriteLock()也是如此。

排它鎖:也稱獨佔鎖、寫鎖或X鎖。如果事務對資料A加上排它鎖後,則其他事務不能再對A加任何型別的鎖。獲得排它鎖的事務即能讀資料又能修改資料。

分散式鎖

我們上面聊的這些鎖,都是在單個程式上面的不同執行緒之間來實現的,那麼當我們的不同程式需要去競爭同一塊資源的時候,這就需要分散式鎖了,我們可以通過redis、zookeeper等中介軟體來實現分散式鎖。

對於鎖來說,其實還有偏向鎖,輕量級鎖等,但是這裡涉及到的內容就比較多,這裡就不在展開篇幅介紹了,有興趣的同學可自行研究,如果你能搞懂上面介紹的這些鎖,那基本上在絕大部分的公司關於“鎖”的問題都可以迎刃而解。

一文徹底搞懂面試中常問的各種“鎖”

喜歡的話,麻煩大家點個贊~關注一下微信公眾號《深夜裡的程式猿》,每天分享最乾的乾貨

相關文章