線程加鎖過程-鎖升級

都說synchronized鎖jdk1.6之前很慢,1.6以後優化的已經很快了,今天看一下到底怎麼個快法了,優化了哪些呢?

大概意思就是jdk1.6以前加鎖就是重量級鎖之後又引入了偏向鎖、輕量級鎖,從而總共有了四種鎖狀態,由低到高爲:無鎖狀態-》偏向鎖狀態-》輕量級鎖狀態-》重量級鎖狀態

1、無鎖狀態

沒有對資源進行鎖定,所有線程都能訪問公共資源

2、偏向鎖

一段同步代碼塊,不存在多線程競爭,而是一直被同一線程多次獲取,從而引入了偏向鎖,來降低鎖的開銷

加鎖:加鎖時進行一次CAS記錄該線程的id,後面只需要判斷是不是同一個線程就行,不需要重複CAS動作了

釋放鎖:此時A線程擁有偏向鎖,線程B進入時,需要等待全局安全點(時間點無字節碼執行),然後暫停擁有偏向鎖的線程,檢查擁有偏向鎖的線程是否存活,如果掛了,直接置爲無鎖狀態,然後B線程加鎖操作,如果處於活動狀態,檢查該對象對偏向鎖的使用情況,如果不使用,直接置爲無鎖狀態,B線程加鎖操作,如果還在使用,那麼進入到輕量級鎖狀態

3、輕量級鎖

線程B處於自旋等待佔用線程A釋放鎖,自旋一定次數後發生鎖升級(鎖膨脹),升級爲重量級鎖;當A線程持有輕量級鎖,B線程在自旋等待,C線程也來競爭鎖時會升級爲重量級鎖

升級輕量級鎖有兩種途徑

1、關閉偏向鎖時,直接進入輕量級鎖

2、A線程持有偏向鎖,B線程來競爭鎖時會升級爲輕量級鎖

4、重量級鎖

重量級鎖就是將爭搶鎖的線程從用戶態轉變爲內核態,讓cpu藉助操作系統來協調線程運行,當A線程持有鎖時,其它線程全部阻塞等待,直到A線程釋放鎖後其它線程再競爭(每次只有一個線程)

當A線程持有輕量級鎖,B線程在自旋等待,C線程也來競爭鎖時會升級爲重量級鎖

整體流程

  1. 線程A進入通過一次CAS加鎖,持有偏向鎖
  2. 線程B進入與線程A發生鎖競爭,產生鎖升級,升級爲輕量級鎖,此時A持有鎖,B自旋等待鎖
  3. 線程C進入與B同時等待,此時鎖升級,進入重量級鎖,此時A持有鎖,B、C處於等待狀態
  4. A釋放鎖後B、C進入鎖競爭

整個狀態只能存在升級即:無鎖-》偏向鎖-》輕量級鎖-》重量級鎖;不存在降級

三種鎖的優缺點:

 備註:

CAS簡介:

需要輸入兩個值,一箇舊的一個新的,先查找出來跟舊值比較,如果相等則替換爲新值,如果不相等重複此操作

優點:通過自旋不斷競爭鎖,不需要線程狀態切換(用戶態和內核態切換)

可能引發問題:

  1. 自旋次數多耗時較長時比較耗CPU
  2. ABA問題,通過新增字段版本號解決
  3. 只能保證一個共享變量的原子操作,jdk1.5後新增了AtomicReference可將多個變量放入對象

 

公衆號主要記錄各種源碼、面試題、微服務技術棧,幫忙關注一波,非常感謝

 

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