ReentrantLock 及 其他鎖 實現原理

2021-10-01 04:55:41 字數 1699 閱讀 5250

reentrantlock 是可重入鎖,什麼是可重入鎖呢?可重入鎖就是當前持有該鎖的執行緒能夠多次獲取該鎖,無需等待。可重入鎖是如何實現的呢?這要從 reentrantlock 的乙個內部類 sync 的父類說起,sync 的父類是 abstractqueuedsynchronizer(後面簡稱aqs)。而synchronized由jvm實現可重入。

判斷競爭.

入佇列

如果隊尾節點不為 null,則說明佇列中已經有執行緒在等待了,那麼直接入隊尾。對於我們舉的例子,這邊的邏輯應該是走 enq,也就是開始隊尾是 null,其實這個時候整個佇列都是 null 的

判斷入佇列後加入頭還是尾

呼叫入口方法acquire(arg)

呼叫模版方法tryacquire(arg)嘗試獲取鎖,若成功則返回,若失敗則走下一步

將當前執行緒構造成乙個node節點,並利用cas將其加入到同步佇列到尾部,然後該節點對應到執行緒進入自旋狀態

自旋時,首先判斷其前驅節點釋放為頭節點&是否成功獲取同步狀態,兩個條件都成立,則將當前執行緒的節點設定為頭節點,如果不是,則利用locksupport.park(this)將當前執行緒掛起 ,等待被前驅節點喚醒

呼叫入口方法release(arg)

呼叫模版方法tryrelease(arg)釋放同步狀態

獲取當前節點的下乙個節點

利用locksupport.unpark(currentnode.next.thread)喚醒後繼節點(接獲取的第四步)

呼叫acquireshared(arg)入口方法

進入tryacquireshared(arg)模版方法獲取同步狀態,如果返返回值》=0,則說明同步狀態(state)有剩餘,獲取鎖成功直接返回

如果tryacquireshared(arg)返回值<0,說明獲取同步狀態失敗,向佇列尾部新增乙個共享型別的node節點,隨即該節點進入自旋狀態

自旋時,首先檢查前驅節點釋放為頭節點&tryacquireshared()是否》=0(即成功獲取同步狀態)

如果是,則說明當前節點可執行,同時把當前節點設定為頭節點,並且喚醒所有後繼節點

如果否,則利用locksupport.unpark(this)掛起當前執行緒,等待被前驅節點喚醒

呼叫releaseshared(arg)模版方法釋放同步狀態

如果釋放成,則遍歷整個佇列,利用locksupport.unpark(nextnode.thread)喚醒所有後繼節點

獨佔鎖的同步狀態值為1,即同一時刻只能有乙個執行緒成功獲取同步狀態

共享鎖的同步狀態》1,取值由上層同步元件確定

獨佔鎖佇列中頭節點執行完成後釋放它的直接後繼節點

共享鎖佇列中頭節點執行完成後釋放它後面的所有節點

共享鎖中會出現多個執行緒(即同步佇列中的節點)同時成功獲取同步狀態的情況

ReentrantLock實現同步

reentrantlock 也可以實現synchronized方法 塊的同步效果。reentrantlock 實現同步 如下 1 新建乙個service類 public class myservice public static void methodb 2 新建乙個測試類 public class...

ReentrantLock之unlock方法分析

public void unlock public final boolean release int arg return false release 1 嘗試在當前鎖的鎖定計數 state 值上減1。成功返回true,否則返回false。當然在release 方法中不僅僅只是將state 1這麼...

ReentrantLock 原理分析

public void lock 這是lock的原始碼,呼叫的其實是sync這個物件的lock函式,而sync是reentrantlock內部類sync的乙個物件例項,他有兩種實現nonfairsync 非公平鎖 和fairsync 公平鎖 先看公平鎖的lock函式 final void lock ...