JDK併發AQS系列(三)
鎖的獲取與釋放
在資料競爭情況下,一個執行緒只有在成功獲取鎖後才能繼續往下執行,當離開競爭區域時將釋放鎖,釋放的鎖供其他即將進入資料競爭區域的執行緒獲取。
同步器一般用acquire和release方法執行獲取釋放鎖操作,acquire方法包括的邏輯是先嚐試獲取鎖,成功則往下執行,否則把執行緒放到等待佇列中並可能將執行緒阻塞;release方法包含的邏輯是釋放鎖,喚醒等待佇列中一個或多個執行緒去嘗試獲取鎖。看看在AQS中鎖的獲取與釋放。
獲取鎖邏輯
if(嘗試獲取鎖失敗) {
建立node
使用CAS方式把node插入到佇列尾部
while(true){
if (嘗試獲取鎖成功 並且 node的前驅節點為頭節點){
把當前節點設定為頭節點
跳出迴圈
}else{
使用CAS方式修改node前驅節點的waitStatus標識為signal
if(修改成功)
掛起當前執行緒
}
}
}
複製程式碼
釋放鎖邏輯
if(嘗試釋放鎖成功){
喚醒後續節點包含的執行緒
}
複製程式碼
自旋鎖
所謂自旋鎖即是某一執行緒去嘗試獲取某個鎖時,如果該鎖已經被其他執行緒佔用的話,此執行緒將不斷迴圈檢查該鎖是否被釋放,而不是讓此執行緒掛起或睡眠。它屬於為了保證共享資源而提出的一種鎖機制,與互斥鎖類似,保證了公共資源在任意時刻最多隻能由一條執行緒獲取使用,不同的是互斥鎖在獲取鎖失敗後將進入睡眠或阻塞狀態。下面利用程式碼實現一個簡單的自旋鎖,
public class SpinLock {
private static Unsafe unsafe = null;
private static final long valueOffset;
private volatile int value = 0;
static {
try {
unsafe=getUnsafeInstance();
valueOffset = unsafe.objectFieldOffset(SpinLock.class
.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private static Unsafe getUnsafeInstance() throws SecurityException,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe" );
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
public void lock() {
for (;;) {
int newV = value + 1;
if(newV==1)
if (unsafe.compareAndSwapInt(this, valueOffset, 0, newV))
return ;
}
}
public void unlock() {
unsafe.compareAndSwapInt(this, valueOffset, 1, 0);
}
}
複製程式碼
這是一個很簡單的自旋鎖,主要看lock和unlock兩個方法,Unsafe僅僅是為操作提供了硬體級別的原子CAS操作,暫時忽略此類,只要知道它的作用即可,我們將在後面的“原子性如何保證”小節中對此進行更加深入的闡述。
對於lock方法,假如有若干執行緒競爭,能成功通過CAS操作修改value值為newV的執行緒即是成功獲取鎖的執行緒,將直接通過,而其他的執行緒則不斷在迴圈檢測value值是否又改回0,將value改為0的操作就是獲取鎖的執行緒執行完後對該鎖進行釋放,通過unlock方法釋放鎖,釋放後若干執行緒又對該鎖競爭。如此一來,沒獲取的鎖也不會被掛起或阻塞,而是不斷迴圈檢查狀態。
根據下圖可加深自旋鎖的理解,五條執行緒輪詢value變數,t1獲取成功後將value置為1,此狀態時其他執行緒無法競爭鎖,t1使用完鎖後將value置為0,剩下的執行緒繼續競爭鎖,以此類推。這樣就保證了某個區域塊的執行緒安全性。
總結
自旋鎖適用於鎖佔用時間短,即鎖保護臨界區很小的情景,同時它需要硬體級別操作,也要保證各快取資料的一致性,另外,無法保證公平性,不保證先到先獲得,可能造成執行緒飢餓。在多處理器機器上,每個執行緒對應的處理器都對同一個變數進行讀寫,而每次讀寫操作都將要同步每個處理器快取,導致系統性能嚴重下降。
-------------推薦閱讀------------
我的開源專案彙總(機器&深度學習、NLP、網路IO、AIML、mysql協議、chatbot)
跟我交流,向我提問:
歡迎關注: