AQS源碼淺析

1、AQS簡介html

AbstractQueuedSynchronizer 抽象隊列同步器。簡稱AQS,同時擁有 同步隊列 與 等待隊列java

2、源碼淺析node

  1. 同步隊列
        線程調用了lock 方法,首先調用 acquire 方法請求鎖,acquire 裏面首先將現場節點封裝Node 加入到同步隊列的隊尾,而後 在 acquireQueued 的循環裏面,while 的判斷 是否是head ,是則直接return 說明獲取到鎖,若是不是 則 調用了 park 方法阻塞,可是while 循環的跳出只能是 當前node 是head 。( 可是前面也說了 head 移除以後會 unpark 後面的結點,而且將後面的setHead) ,因此對於每一個在抽象隊列同步器的同步隊列裏面的Node,都是阻塞的,可是同步器每次acquire都會有一個acquireQueued ,至關於每一個Node 都會 循環的請求,可是循環是同步器發出的,相似於一個「自旋」,這個自旋是 同步器控制的,線程仍是阻塞的。
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

  2. 等待隊列函數

        調用 await 方法,進入condition的等待隊列,釋放鎖,進入一個 while 循環,只有當線程回到同步隊列或者被中斷才能夠跳出while,while裏面 park 掉線程 ----- 在 condition調用 signal 以後,該condition上面的節點的 firstWaiter 首先加入到 同步隊列尾部 , 會 unpark 線程,退出 while 以後,又會進入 acquireQueued 的循環裏面,一樣存在以前的邏輯。工具

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    Node node = addConditionWaiter();
    int 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);
}

  3. 總結ui

    • 等待隊列,是已經獲取到鎖的線程,須要用到其餘線程的數據,主動調用 wait() 方法,而且釋放鎖,喚醒同步隊列的後繼節點(非公平不用喚醒),而後當前節點構造新的Node進入等待隊列,當有其餘 在同步隊列裏面 已經得到鎖的線程調用 notify()(或者 signal())以後,纔會從新加入同步隊列,嘗試獲取鎖。 等待隊列的節點也調用了 park () 方法阻塞。
    • Condition 接口中的 await() 與 signal() 函數分別用於 是線程進行等待狀態---加入到等待隊列中 、喚醒等待隊列中的首節點的線程。
    • 在ReetrantLock 裏面,公平與非公平自旋鎖,也是基於 同步器的,同步器的隊列是默認阻塞的 ,ReetrantLock 裏面是自旋非阻塞的。compareAndSetState
    • ReetrantLock 裏面 公平與非公平的自旋鎖,都是在一直自旋沒有 park(), 公平多了一個判斷當前節點是否有前驅節點語句
      if (!hasQueuedPredecessors()...

3、工具類this

  • LockSupport
定義了一系列的公有靜態方法,用於 阻塞&&喚醒 一個線程。
LockSupport 中的park 與 unpark 等方法,最終都是調用的 Unsafe 類中的方法,而 Unsafe 類中提供的是一系列的硬件級別的原子操做 ,有點相似於 彙編級別或者機器碼級別 指令同樣

 

轉載請註明地址:https://www.cnblogs.com/handsomecui/p/14253284.html線程

相關文章
相關標籤/搜索