一文完全搞懂面試中常問的各類「鎖」

前言java

鎖,顧名思義就是鎖住一些資源,當只有咱們拿到鑰匙的時候,才能操做鎖住的資源。在咱們的Java,數據庫,還有一些分佈式的環境中,老是充斥着各類各樣的鎖讓人頭疼,例如「公平鎖」、「自旋鎖」、「讀寫鎖」、「分佈式鎖」等等。redis

其實真實的狀況是,鎖並無那麼多,不少概念只是從不一樣的功能特性,設計,以及鎖的狀態這些不一樣的側重點來講明的,所以咱們能夠根據不一樣的分類來搞明白爲何會有這些「鎖」?坐穩扶好了,準備開車。數據庫

正文微信

「公平鎖」與「非公平鎖」併發

公平鎖:指線程在等待獲取同一個鎖的時候,是嚴格按照申請鎖的時間順序來進行的,這就意味着在程序正常運做的時候,不會有線程執行不到,而被「餓死」,可是也須要額外的機制來維護這種順序,因此效率相對於非公平鎖會差點。分佈式

非公平鎖:概念跟「公平鎖」偏偏相反,隨機線程獲取鎖,相率相對高。this

new ReentrantLock(); //默認非公平鎖
new ReentrantLock(true); //公平鎖
複製代碼

「重入鎖(遞歸鎖)」與「不可重入鎖(自旋鎖)」spa

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

重入鎖:當一個線程獲取了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等中間件來實現分佈式鎖。

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

喜歡的話,麻煩你們點個贊~關注一下微信公衆號《深夜裏的程序猿》,天天分享最乾的乾貨
相關文章
相關標籤/搜索