關鍵資訊
state(volatile修飾)/雙向連結串列資料結構
AQS有那些實現?
ReentrantLock、Semaphore、CountDownLatch
AQS分為同步佇列和條件佇列
public class BoundedBuffer<T> {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Object[] items = new Object[10];
private int putpos = 0;
private int takepos = 0;
private int count = 0;
public void put(T x) throws InterruptedException {
lock.lock();
try {
while (count == items.length) {
notFull.await(); // 等待緩衝區不滿
}
items[putpos] = x;
if (++putpos == items.length) putpos = 0;
++count;
notEmpty.signal(); // 通知等待的消費者
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await(); // 等待緩衝區不為空
}
T x = (T) items[takepos];
items[takepos] = null;
if (++takepos == items.length) takepos = 0;
--count;
notFull.signal(); // 通知等待的生產者
return x;
} finally {
lock.unlock();
}
}
同步佇列如何實現的?
是透過ConditionObject實現的,裡面個雙向佇列
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
/** First node of condition queue. */
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//將當前執行緒加入等待佇列
Node node = addConditionWaiter();
//釋放當前的鎖
long savedState = fullyRelease(node);
int interruptMode = 0;
//不在同步佇列,則繼續等待
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//將執行緒加入到等待佇列
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//獲取佇列首個節點
Node first = firstWaiter;
if (first != null)
//喚醒隊首執行緒
doSignal(first);
}