基於AQS的獨佔鎖實現邏輯

2021-10-23 18:54:55 字數 3179 閱讀 2174

獨佔鎖的正常使用方式,先從加鎖邏輯開始。

lock lock =

newreentrantlock()

;public

void

test()

finally

}

reentrantlock分公平鎖和非公平鎖,公平鎖指搶鎖的執行緒進來先入佇列排隊,按照fifo的方式獲取鎖。而非公平鎖指執行緒開始可以插隊嘗試獲取鎖,如果獲取失敗,才入佇列排隊,接著按照fifo的方式獲取鎖。其實非公平鎖的後一部分邏輯和公平鎖一樣,下面以非公平鎖分析。

final

void

lock()

下面接著看acquire(1):

public

final

void

acquire

(int arg)

下面把acquire(int arg)下的幾個方法拆開來看:

protected

final

boolean

tryacquire

(int acquires)

final

boolean

nonfairtryacquire

(int acquires)

}//如果c!=0,判斷持有鎖的執行緒是否是當前執行緒,這裡支援鎖的可重入性

else

if(current ==

getexclusiveownerthread()

)//拿鎖失敗

return

false

;}

分析完了acquire(1),接下來分析addwaiter(node.exclusive),走到這裡說明鎖被其他執行緒拿去了:

private node addwaiter

(node mode)

}//如果走到這裡,說明更新尾節點失敗,進入自旋,不斷嘗試將自己新增到尾節點

enq(node)

;return node;

}

private node enq

(final node node)

else}}

}

這時候已經將新節點新增到佇列尾部了,接下來往下看:

//node就是新加進去的尾節點

final

boolean

acquirequeued

(final node node,

int arg)if(

shouldparkafte***iledacquire

(p, node)

&&parkandcheckinterrupt()

) interrupted =

true;}

}finally

}

下面是掛起邏輯:

private

static

boolean

shouldparkafte***iledacquire

(node pred, node node)

while

(pred.waitstatus >0)

; pred.next = node;

}else

//返回false後會進入for(;;)的下一次自旋

return

false

;}

在上述**中返回true後,下面是真正的掛起邏輯,將當前執行緒掛起,避免無休止的自旋消耗cpu資源。注意,後面將喚醒已掛起的執行緒的時候,從這裡開始喚醒,成功獲取鎖,走完lock.lock()方法,進入業務**:

private

final

boolean

parkandcheckinterrupt()

釋放鎖的邏輯,無**平鎖還是非公平鎖都是一樣的。

public

void

unlock()

//釋放鎖

public

final

boolean

release

(int arg)

return

false

;}

嘗試釋放鎖:

protected

final

boolean

tryrelease

(int releases)

setstate

(c);

//標誌是否釋放了鎖

return free;

}

喚醒後繼節點:

private

void

unparksuccessor

(node node)

//喚醒執行緒

if(s != null)

locksupport.

unpark

(s.thread)

;}

在獲取同步狀態時,同步器維護乙個同步佇列,獲取狀態失敗的執行緒都會被加入到佇列中並在佇列中進行自旋;移出佇列(或停止自旋)的條件是前驅節點為頭節點且成功獲取了同步狀態。在釋放同步狀態時,同步器呼叫tryrelease(int arg)方法釋放同步狀態,然後喚醒head指向節點的後繼節點。
節點加入到鍊錶尾部和從鍊錶移出示意圖通過上面的原始碼分析,結合下圖理解。

節點加入到鍊錶尾部:

節點從鍊錶移除:

獨佔式同步狀態獲取與釋放流程圖:

併發程式設計核心框架AQS之獨佔鎖原理詳解

如何設計符合冪等性的高質量restful api 理解restful的冪等性,並且設計符合冪等規範的高質量restful api。http冪等方法,是指無論呼叫多少次都不會有不同結果的 http 方法。不管你呼叫一次,還是呼叫一百次,一千次,結果都是相同的。還是以之前的博文的例子為例。get tic...

JUC併發基石之AQS原始碼解析 獨佔鎖的釋放

juc併發基石之aqs原始碼解析 獨佔鎖的獲取public final boolean release int arg return false 獨佔鎖的涉及到兩個函式的呼叫 1.tryrelease arg 該方法由aqs的子類來實現釋放鎖的具體邏輯 2.unparksuccessor h 喚醒後...

AQS共享鎖的實現原理

前面的文章lock的實現中分析了aqs獨佔鎖的實現原理,那麼接下來就分析下aqs是如何實現共享鎖的。共享鎖的介紹 共享鎖 同一時刻有多個執行緒能夠獲取到同步狀態。那麼它是如何做到讓多個執行緒獲取到同步狀態呢?來看一下獲取共享鎖的過程 1.執行緒呼叫aqs的acquireshared 申請獲取鎖 可有...