我們呼叫semaphore方法時,其實是在間接呼叫其內部類或aqs方法執行的。semaphore類結構與reetrantlock類相似,內部類sync繼承自aqs,然後其子類fairsync和nofairsync分別實現公平鎖和非公平鎖的獲取鎖方法tryacquireshared(int arg)
,而釋放鎖的tryreleaseshared(int arg)
方法則有sync類實現,因為非公平或公平鎖的釋放過程都是相同的。
aqs通過state值來控制對共享資源訪問的執行緒數,有執行緒請求同步狀態成功state值減1,若超過共享資源數量獲取同步狀態失敗,則將執行緒封裝共享模式的node結點加入到同步佇列等待。有執行緒執行完任務釋放同步狀態後,state值會增加1,同步佇列中的執行緒才有機會獲得執行權。公平鎖與非公平鎖不同在於公平鎖申請獲取同步狀態前都會先判斷同步佇列中釋放存在node,若有則將當前執行緒封裝成node結點入隊,從而保證按fifo的方式獲取同步狀態,而非公平鎖則可以直接通過競爭獲取執行緒執行權。
//semaphore的acquire()
public
void acquire() throws
interruptedexception
/*** 注意sync類繼承自aqs
* aqs的acquiresharedinterruptibly()方法
*/public
final
void acquiresharedinterruptibly(int
arg)
throws
interruptedexception
//semaphore中非公平鎖nonfairsync的tryacquireshared()
protected
int tryacquireshared(int
acquires)
final
int nonfairtryacquireshared(int
acquires)
}private
void doacquiresharedinterruptibly(int
arg)
throws
interruptedexception
}//調整同步佇列中node結點的狀態並判斷是否應該被掛起
//並判斷是否需要被中斷,如果中斷直接丟擲異常,當前結點請求也就結束
if (shouldparkafte***iledacquire(p, node) &&parkandcheckinterrupt())
throw
newinterruptedexception();}}
finally
}private
static
boolean
shouldparkafte***iledacquire(node pred, node node)
while (pred.waitstatus > 0);
pred.next =node;
} else
return
false
; }
private
final
boolean
parkandcheckinterrupt()
//不可中的acquireshared()
public
final
void acquireshared(int
arg)
private
void doacquireshared(int
arg)
}if (shouldparkafte***iledacquire(p, node) &&parkandcheckinterrupt())
//沒有丟擲異常中的。。。。
interrupted = true
; }
} finally
}private
void setheadandpropagate(node node, int
propagate)
}//semaphore的release()
public
void
release()
//呼叫到aqs中的releaseshared(int arg)
public
final
boolean releaseshared(int
arg)
return
false
; }
//在semaphore的內部類sync中實現的
protected
final
boolean tryreleaseshared(int
releases)
}private
void
doreleaseshared()
else
if (ws == 0 &&
!compareandsetwaitstatus(h, 0, node.propagate))
continue; //
loop on failed cas
}
//如果頭結點發生變化,則繼續迴圈。否則,退出迴圈。
if (h == head) //
loop if head changed
break
; }}//
喚醒傳入結點的後繼結點對應的執行緒
private
void
unparksuccessor(node node)
if (s != null
)
//喚醒該執行緒
locksupport.unpark(s.thread);
}
剖析基於併發aqs的共享鎖的實現(基於訊號量semaphore)
AQS(三) 共享鎖
共享式獲取同步狀態,與獨佔式的區別在於同一時刻有多個執行緒獲取同步狀態 共享式獲取同步狀態,與獨佔式的區別在於同一時刻有多個執行緒獲取同步狀態 void acquireshared int arg 在acquireshared方法基礎上增加了能響應中斷的功能 void acquiresharedin...
AQS共享鎖的實現原理
前面的文章lock的實現中分析了aqs獨佔鎖的實現原理,那麼接下來就分析下aqs是如何實現共享鎖的。共享鎖的介紹 共享鎖 同一時刻有多個執行緒能夠獲取到同步狀態。那麼它是如何做到讓多個執行緒獲取到同步狀態呢?來看一下獲取共享鎖的過程 1.執行緒呼叫aqs的acquireshared 申請獲取鎖 可有...
深入淺出AQS之共享鎖模式
在了解了aqs獨佔鎖模式以後,接下來再來看看共享鎖的實現原理。搞清楚aqs獨佔鎖的實現原理之後,再看共享鎖的實現原理就會輕鬆很多。兩種鎖模式之間很多通用的地方本文只會簡單說明一下,就不在贅述了,具體細節可以參考我的上篇文章深入淺出aqs之獨佔鎖模式 一 執行過程概述 獲取鎖的過程 當執行緒呼叫acq...