【Java面試】為什麼引入偏向鎖、輕量級鎖,介紹下升級流程

跟著Mic學架構發表於2022-06-18

Hi,我是Mic

一個工作了7年的粉絲來找我,他說最近被各種鎖搞暈了。

比如,共享鎖、排它鎖、偏向鎖、輕量級鎖、自旋鎖、重量級鎖、

間隙鎖、臨鍵鎖、意向鎖、讀寫鎖、樂觀鎖、悲觀鎖、表鎖、行鎖。

然後前兩天去面試,被問到偏向鎖、輕量級鎖,結果沒回答上來。

ok,關於Synchronized鎖升級的原理,看看普通人和高手的回答。

普通人:

我覺得引入這些鎖的目的應該是考慮到那個效能問題吧。

因為我記得好像是說Synchronized裡面去加重量級鎖的話,它的這個執行緒會存在這個阻塞就是會影響效能。所以才引入了偏向鎖的一個機制。

然後升級的話就是說我們那些獲取鎖的時候就是按照偏向鎖、輕量級鎖和重量級鎖的方式去競爭鎖吧。

高手:

好的,面試官。

  1. Synchronized在jdk1.6版本之前,是通過重量級鎖的方式來實現執行緒之間鎖的競爭。

    之所以稱它為重量級鎖,是因為它的底層底層依賴作業系統的Mutex Lock來實現互斥功能。

    Mutex是系統方法,由於許可權隔離的關係,應用程式呼叫系統方法時需要切換到核心態來執行。

    這裡涉及到使用者態向核心態的切換,這個切換會帶來效能的損耗。

    image-20220509111625747

  2. 在jdk1.6版本中,synchronized增加了鎖升級的機制,來平衡資料安全性和效能。簡單來說,就是執行緒去訪問synchronized同步程式碼塊的時候,synchronized根據

    執行緒競爭情況,會先嚐試在不加重量級鎖的情況下去保證執行緒安全性。所以引入了偏向鎖和輕量級鎖的機制。

    偏向鎖,就是直接把當前鎖偏向於某個執行緒,簡單來說就是通過CAS修改偏向鎖標記,這種鎖適合同一個執行緒多次去申請同一個鎖資源並且沒有其他執行緒競爭的場景。

    輕量級鎖也可以稱為自旋鎖,基於自適應自旋的機制,通過多次自旋重試去競爭鎖。自旋鎖優點在於它避免避免了使用者態到核心態的切換帶來的效能開銷。

  1. Synchronized引入了鎖升級的機制之後,如果有執行緒去競爭鎖:

​ 首先,synchronized會嘗試使用偏向鎖的方式去競爭鎖資源,如果能夠競爭到偏向鎖,表示加鎖成功直接返回。如果競爭鎖失敗,說明當前鎖已經偏向了其他執行緒。

​ 需要將鎖升級到輕量級鎖,在輕量級鎖狀態下,競爭鎖的執行緒根據自適應自旋次數去嘗試搶佔鎖資源,如果在輕量級鎖狀態下還是沒有競爭到鎖,

​ 就只能升級到重量級鎖,在重量級鎖狀態下,沒有競爭到鎖的執行緒就會被阻塞,執行緒狀態是Blocked。

​ 處於鎖等待狀態的執行緒需要等待獲得鎖的執行緒來觸發喚醒。

image-20220509113906275

總的來說, Synchronized的鎖升級的設計思想,在我看來本質上是一種效能和安全性的平衡,也就是如何在不加鎖的情況下能夠保證執行緒安全性。

這種思想在程式設計領域比較常見,比如Mysql裡面的MVCC使用版本鏈的方式來解決多個並行事務的競爭問題。

以上就是我對這個問題的理解。

總結

鎖在程式中是非常常見的內容,我們幾乎每天與鎖打交道,比如Mysql裡面的行鎖、表鎖。

因此它的重要性也不言而喻。

我們從高手的回答中可以明顯的看到高手對Synchronized的理解層次是非常高的。

喜歡我的作品的小夥伴記得點贊和收藏加關注。

file

版權宣告:本部落格所有文章除特別宣告外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 Mic帶你學架構
如果本篇文章對您有幫助,還請幫忙點個關注和贊,您的堅持是我不斷創作的動力。歡迎關注同名微信公眾號獲取更多技術乾貨!

相關文章