AQS解析

辉辉、發表於2024-08-15
關鍵資訊
state(volatile修飾)/雙向連結串列資料結構
AQS解析
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);
}

相關文章