佇列同步器

2021-12-29 19:55:00 字數 1968 閱讀 3857

1、abstractqueuedsynchronizer

頭節點:獲取同步狀態成功的節點

尾節點:執行緒無法獲取到同步狀態,而被構造成節點,加入到同步佇列。

加入佇列必須保證執行緒安全:

compareandsettail(node expect, node update);

2、獨佔式同步

1)獲取同步狀態

public final void acquire(int arg) 首先tryaquire(int arg)方法獲取同步狀態,若獲取失敗,則構造同步節點(獨佔式節點,node.exclusive,即乙個時刻只能有乙個執行緒成功獲取同步狀態),

然後加入同步佇列的尾部(addwaitor(node node)),

private node addwaiter(node mode)

}enq(node);

return node;

}private node enq(final node node) else }}

}最後以「死迴圈」方式獲取同步狀態(acquirequeued(node node, int arg)),若獲取不到則執行緒一直阻塞。

final boolean acquirequeued(final node node, int arg)

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

parkandcheckinterrupt())

interrupted = true;

}} finally

}只有頭節點才能獲取同步狀態,頭節點成功獲取同步狀態之後,釋放自己的同步狀態,喚醒其後繼節點。

節點自旋:每個節點自省觀察前驅節點是否是頭節點,若是,則獲取到同步狀態,自動退出自旋過程。

2)釋放同步狀態

public final boolean release(int arg)

return false;

}同步器釋放同步狀態(tryrelease(int arg)),並喚醒等待執行緒(unparksuccessor方法使用locksupport來喚醒處於等待狀態的執行緒)。

3)總結

進佇列:獲取同步狀態時,獲取失敗的執行緒會加入到同步佇列中,並進行自旋;

出佇列:頭節點成功獲取同步狀態,然後釋放同步狀態,喚醒後繼節點。

2、共享式同步狀態

共享式與獨佔式最主要區別:同一時刻能否有多個執行緒獲取到同步狀態。

1)獲取同步狀態

public final void acquireshared(int arg) private void doacquireshared(int arg)

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

parkandcheckinterrupt())

interrupted = true;

}} finally

}同步器嘗試獲取同步狀態,tryacquireshared(int arg)返回int型別,當返回值大於0時,表示能夠獲取到同步狀態;

返回值小於0時,進入doacquireshared(int arg)自旋。

2)釋放同步狀態

public final boolean releaseshared(int arg)

return false;

}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;

}}釋放同步狀態後,喚醒後續處於等待狀態的節點,對於同時釋放來自多個執行緒的同步狀態,一般通過迴圈和cas來保證。

佇列同步器的分析

包括 同步佇列,獨佔式同步狀態獲取與釋放 共享式同步狀態獲取與釋放 1.同步佇列 aqs依賴內部的同步佇列 乙個fifo雙向佇列 來完成同步狀態管理。當執行緒獲取同步狀態失敗時,同步器會將當前執行緒和等待狀態等資訊包裝成乙個節點並將其加入同步佇列,同時會阻塞當前執行緒。當同步狀態釋放時,會把首節點中...

抽象佇列同步器AQS

aqs具體實現及內部原理 aqs同步佇列具體實現結構 private volatile int state 共享變數,使用volatile修飾保證執行緒可見性share共享 多個執行緒可同時執行,如reentrantreadwritelock.readlock cyclicbarrier count...

同步器AQS中的同步佇列與等待佇列

在單純地使用鎖,比如reentrantlock的時候,這個鎖元件內部有乙個繼承同步器aqs的類,實現了其抽象方法,加鎖 釋放鎖也只是涉及到aqs中的同步佇列而已,那麼等待佇列又是什麼呢?當使用condition的時候,等待佇列的概念就出來了。condition的獲取一般都要與乙個鎖lock相關,乙個...