Lock底層原理

一、概述

Lock 有三個實現類,一個是 ReentrantLock, 另兩個是 ReentrantReadWriteLock 類中的兩個靜態內部類 ReadLock 和 WriteLock。
在這裏插入圖片描述

LOCK 的實現類其實都是構建在 AbstractQueuedSynchronizer 上,爲何圖中沒有用 UML 線表示呢,這是每個 Lock 實現類都持有自己內部類 Sync 的實例,而這個 Sync 就是繼承 AbstractQueuedSynchronizer (AQS)。爲何要實現不同的 Sync 呢?這和每種 Lock 用途相關。另外還有 AQS 的 State 機制。

FairSync 與 NonfairSync 的區別在於,是不是保證獲取鎖的公平性,因爲默認是 NonfairSync(非公平性)


二、AQS

可以看到Lock鎖的底層實現是AQS

1.定義

AQS(AbstractQuenedSynchronizer ),抽象的隊列式同步器,除了 java 自帶的 synchronized 關鍵字之外的鎖機制。

2.AQS 的核心思想

如果被請求的共享資源空閒,則將當前請求資源的線程設置爲有效的工作線程,並將共享資源設置爲鎖定狀態,如果被請求的共享資源被佔用,那麼就需要一套線程阻塞等待以及被喚醒時鎖分配的機制,這個機制 AQS 是用 CLH 隊列鎖(CLH 鎖是一個自旋鎖。能確保無飢餓性。提供先來先服務的公平性)實現的,即將暫時獲取不到鎖的線程加入到隊列中。

AQS 是將每一條請求共享資源的線程封裝成一個 CLH 鎖隊列的一個結點(Node),來實現鎖的分配。

3.實現

AQS 基於 CLH 隊列,用 volatile 修飾共享變量 state,線程通過 CAS 去改變狀態符,成功則獲取鎖成功,失敗則進入等待隊列,等待被喚醒。

4.總結

  • lock 的存儲結構:一個 int 類型狀態值(用於鎖的狀態變更),一個雙向鏈表(用於存儲等待中的線程)
  • lock 獲取鎖的過程:本質上是通過 CAS 來獲取狀態值修改,如果當場沒獲取到,會將該線程放在線程等待鏈表中。
  • lock 釋放鎖的過程:修改狀態值,調整等待鏈表。

可以看到在整個實現過程中,lock 大量使用 CAS + 自旋。因此根據 CAS 特性,lock 建議使用在低鎖衝突的情況下。目前 java1.6 以後,官方對 synchronized 做了大量的鎖優化(偏向鎖、自旋、輕量級鎖)。因此在非必要的情況下,建議使用 synchronized 做同步操作。


【Java 面試那點事】

這裏致力於分享 Java 面試路上的各種知識,無論是技術還是經驗,你需要的這裏都有!

這裏可以讓你【快速瞭解 Java 相關知識】,並且【短時間在面試方面有跨越式提升

面試路上,你不孤單!
在這裏插入圖片描述

發佈了165 篇原創文章 · 獲贊 852 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章