AQS共享鎖的實現原理

2021-08-09 13:45:10 字數 2250 閱讀 3611

前面的文章lock的實現中分析了aqs獨佔鎖的實現原理,那麼接下來就分析下aqs是如何實現共享鎖的。

共享鎖的介紹

共享鎖:同一時刻有多個執行緒能夠獲取到同步狀態。

那麼它是如何做到讓多個執行緒獲取到同步狀態呢?

來看一下獲取共享鎖的過程:

1. 執行緒呼叫aqs的acquireshared()申請獲取鎖(可有多個執行緒獲取到,根據重寫的tryacquireshared()方法決定),如果成功則進入臨界區。

2. 如果失敗,建立乙個共享型的節點進入fifo等待佇列,阻塞然後等待喚醒。

3. 等待佇列中的執行緒被喚醒重新嘗試獲取鎖,獲取成功後根據state變數值決定是否繼續喚醒後續節點(如果state值為0,表示沒有可用的鎖,不喚醒後繼節點;如果state的值》0,表示有可用的鎖,喚醒後繼節點),獲取失敗則繼續等待,直到成功。

釋放共享鎖的過程:

1. 執行緒呼叫releaseshared()進行鎖資源釋放,如果釋放成功則喚醒佇列中等待的節點(如果有)。

共享式獲取鎖

執行緒呼叫acquireshared()方法獲取鎖:

public

final

void

acquireshared(int arg)

分析如下:

private

void

doacquireshared(int arg)

}if (shouldparkafte***iledacquire(p, node) &&

parkandcheckinterrupt())

interrupted = true;

}} finally

}

可以看到,當前驅節點是頭節點head時,執行緒嘗試獲取鎖,此時注意返回值r,有以下三種可能:

那麼就來看一下setheadandpropagate(node, r)這個方法:

private

void

setheadandpropagate(node node, int propagate)

}

根據r的值判斷,r>0時,表示可以喚醒後繼節點,執行doreleaseshared()方法;而當r=0時,不會直接執行doreleaseshared()方法,而是進入第二種情況繼續判斷;

頭節點後面的節點需要被喚醒(waitstatus<0),不論是老的頭結點還是新的頭結點

接下來看看doreleaseshared()這個方法:

private

void

doreleaseshared()

else

if (ws == 0 &&

!compareandsetwaitstatus(h, 0, node.propagate))

continue; //如果後繼節點暫時不需要喚醒,則把當前節點狀態設定為propagate確保以後可以傳遞下去

}if (h == head) // loop if head changed

break;

}}

這裡有兩個入口可以進入該方法,乙個是直接釋放鎖releaseshared()乙個是上述setheadandpropagate()方法,因此在釋放鎖的過程中需要使用cas操作保證執行緒安全。

進入第乙個if語句,表示後繼節點需要被喚醒,採用cas迴圈操作直到成功;

進入else if語句,表示暫時不需要喚醒,將狀態傳遞;

最後判斷頭節點是否變化,沒有變化則退出迴圈;如果頭結點發生變化,比如說其他執行緒獲取到了鎖,為了使自己的喚醒動作可以傳遞,必須進行重試

以上就是獲取共享鎖的大致過程。

共享式釋放鎖

呼叫releaseshared()方法主動釋放鎖:

public

final

boolean

releaseshared(int arg)

return

false;

}

可以看到,當重寫的tryreleaseshared(arg)方法返回true,成功釋放鎖資源,進入doreleaseshared()喚醒等待的執行緒,這個方法上面已經分析過,這裡不再贅述。

共享鎖的實現稍比獨佔鎖複雜,但大同小異。二者對比如下:

獨佔鎖:

共享鎖:

AQS共享鎖應用之Semaphore原理

我們呼叫semaphore方法時,其實是在間接呼叫其內部類或aqs方法執行的。semaphore類結構與reetrantlock類相似,內部類sync繼承自aqs,然後其子類fairsync和nofairsync分別實現公平鎖和非公平鎖的獲取鎖方法tryacquireshared int arg 而...

AQS(三) 共享鎖

共享式獲取同步狀態,與獨佔式的區別在於同一時刻有多個執行緒獲取同步狀態 共享式獲取同步狀態,與獨佔式的區別在於同一時刻有多個執行緒獲取同步狀態 void acquireshared int arg 在acquireshared方法基礎上增加了能響應中斷的功能 void acquiresharedin...

AQS鎖機制原理

reentrantreadwritelock 與 reentrantlock 核心就是 sync aqs子類 及aqs synchronized基於 內部物件鎖 jvm指令的級別 reentrantreadwritelock 引用傳入 內部類 readlock和writelock,將其sync傳入兩...