【多線程】鎖的七大分類


鎖的七大類

在Java的多線程中,有很多種鎖,每種鎖可能同時占有多個標准,比如ReentranLock即可是中斷鎖,又可以是可重入鎖。

那么根據分類標准,我們可以把這些鎖分為以下七大標准,分別是:

  • 偏向鎖/輕量級鎖/重量級鎖
  • 可重入鎖/非可重入鎖
  • 共享鎖/獨占鎖
  • 公平鎖/非公平鎖
  • 悲觀鎖/樂觀鎖
  • 自旋鎖/非自旋鎖
  • 可中斷鎖/不可中斷鎖

偏向鎖/輕量級鎖/重量級鎖

這三種鎖特指 synchronized 鎖的狀態,通過在對象頭種的mark word來表明鎖的狀態。

偏向鎖

在被synchronized修飾的情況下,當前正在執行synchronized的線程,有且只有一個線程來獲取synchronized的鎖,這個時候系統就會給他升級為偏向鎖,因為前來獲取鎖的線程並沒有其他現在來競爭獲取,所以系統只需要給他打一個標記,告訴它下一次的鎖直接給他,這樣就可以直接獲得鎖,並且開銷也是最小的。

輕量級鎖

滿足輕量級鎖的條件

  1. 被synchronized進行修飾的鎖
  2. 被多個線程交替執行的,不是同時執行,不存在實際的競爭
  3. 只有短時間的鎖競爭
    如果滿足上面三種情況,synchronized鎖的狀態就會從偏向鎖升級為輕量級鎖,線程會通過自旋的形式來獲取鎖,而不會陷入阻塞

重量級鎖

滿足重量級鎖的條件

  1. 被synchronized進行修飾的鎖
  2. 被多個線程交替執行的並且是同時執行
  3. 鎖的競爭時間較長
    重量級鎖是互斥鎖,他利用的是操作系統的同步機制來實現的,所以開銷會比偏量鎖和輕量鎖的開銷都大,當滿足上面的條件后,輕量級鎖就會升級為重量級鎖,重量級鎖就會讓其他申請卻拿不到鎖的線程進入到阻塞狀態。

鎖升級路線

image.png
結合上面的描述,我們其實可以發現得到對於synchronized鎖的升級路線,並且性能也是由着鎖升級的推進,性能的開銷也會變的越來越大。

可重入鎖/非可重入鎖

可重入鎖:一個線程內可以同時獲取一把鎖多次
比如在線程A中有一把B鎖,如果A在獲取到B鎖的情況下,再次去獲取B鎖,如果可以獲取到B鎖,那么他就是一把可重入鎖。
例子:ReentrantLock

不可重入鎖:一個線程內只能同時擁有一把鎖一次
比如在線程A中有一把B鎖,如果A線程在獲取到B鎖的情況下,想再次去獲取到B鎖卻失敗了,需要釋放到之前的B鎖,然后再去獲取B鎖,那么這樣就是一個不可重入鎖。

共享鎖/獨占鎖

共享鎖:可以同時被多個線程獲取到鎖,例如我們常見的讀操作,它並不影響數據,所以可以被允許將鎖給多個線程同時訪問。
獨占鎖:有且只能被一個鎖獨占訪問,這種就常用到我們的寫操作上,由於需要保證數據的一致性和原子性。就需要在數據的寫操作上只能允許一個線程來訪問使用。

公平鎖/非公平鎖

公平鎖:遵循先來先得的規則,如果線程在搶不到鎖的情況下,會進入到排序的狀態中,最先排隊靠前的鎖就會最顯輪到獲取鎖。
非公平鎖:在公平鎖的規則基礎上,會在一定的情況下導致鎖插隊。

自旋鎖/非自旋鎖

自旋鎖的理念就是在線程拿不到鎖的時候,它並不會進入到阻塞狀態或者釋放掉CPU的資源,它是直接去循環的去訪問鎖的狀態,不斷的去嘗試獲取鎖,這個循環的過程也被叫做自旋。
非自旋鎖就跟自旋鎖相反,他沒獲取到鎖他就不會再去嘗試獲取,但是他會直接去排隊或者陷入阻塞狀態中。

可中斷鎖/不可中斷鎖

顧名思義,可中斷鎖就是在獲取到鎖后可以中斷他的任務然后去做其他的任務,最典型的就是使用ReentrantLock,它就是一種典型的可中斷鎖,例如使用lockInterruptibly方法再獲取鎖的過程中,突然不想獲取了,那么也可以在中斷之后去做其他的事情,不需要一直傻等到獲取鎖才離開

不可中斷鎖就沒有那么靈活,典型的就是synchronized,一旦申請了鎖,那么就沒有回頭路了,只能等到拿到鎖以后才能進行其他的邏輯處理。


免責聲明!

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



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