java并發(fā)編程(十七)帶你了解什么是面試官常說的AQS

前面我們學(xué)習(xí)了ReentrantLock,其底層就是用了AQS實現(xiàn)的,應(yīng)該先講這一章節(jié),但是當時給忘了,現(xiàn)在給補上吧。

關(guān)于ReentrantLock的學(xué)習(xí),可以參考:http://www.itdecent.cn/p/edec5185196d

AbstractQueuedSynchronizer是阻塞式鎖,以及同步器組件的實現(xiàn)框架。是JDK中實現(xiàn)并發(fā)編程的核心,它提供了一個基于FIFO隊列,平時我們工作中經(jīng)常用到的ReentrantLock,CountDownLatch等都是基于它來實現(xiàn)的。

一、初識AQS

首先我們還是從前面學(xué)習(xí)的ReentrantLock入手,看看其代碼結(jié)構(gòu)是什么樣的:

ReentrantLockl類圖

從上圖可以看到以下幾點:

  • ReentrantLock實現(xiàn)接口Lock(抽象接口)
  • ReentrantLock有三個內(nèi)部類,分別是FrairSync、NonfairSync、Sync,且FrairSync、NonfairSync繼承自Sync。
  • Sync繼承AbstractQueuedSynchronizer
  • AbstractQueuedSynchronizer有兩個內(nèi)部類,分別是Node、ConditionObject。
  • AbstractQueuedSynchronizer繼承自AbstractOwnableSynchronizer(抽象類,提供獨占線程的get和set)。

AQS有如下的特點:

  • 用 state 屬性來表示資源的狀態(tài),包含獨占狀態(tài)和共享狀態(tài),對應(yīng)公平鎖和非公平鎖。子類需要定義如何維護這個狀態(tài),控制如何獲取鎖和釋放鎖,如上面圖中的關(guān)系,公平鎖和非公平鎖需要各自去維護這個state,達到獲取和釋放鎖的目的。

    • getState - 獲取 state 狀態(tài)
    • setState - 設(shè)置 state 狀態(tài)
    • compareAndSetState - 使用CAS設(shè)置狀態(tài)
    • 獨占模式:只有一個線程能夠訪問資源
    • 共享模式:允許多個線程訪問資源
  • 提供了基于 FIFO 的等待隊列,類似于前面講Synchronized原理提到的 Monitor 的 EntryList

  • 使用條件變量來實現(xiàn)等待隊列、線程喚醒機制,同時支持多個條件變量,類似于前面講Synchronized原理提到的 Monitor 的 WaitSet

  • 【公平鎖】與【非公平鎖】:二者的區(qū)別主要在于獲取鎖是否和排隊順序有關(guān)。當鎖唄一個線程持有,其他嘗試獲取鎖的線程會被掛起,加到等待隊列中,先被掛起的在隊列的最前端。當鎖被釋放,需要通知隊列中的線程。作為公平鎖,會先喚醒隊列最前端的線程;而非公平鎖會喚醒所有線程,通過競爭去獲取鎖,后來的線程有可能獲得鎖。

二、 源碼分析

下面我們通過源碼剖析其本質(zhì)是什么樣的。

首先在腦海中有個印象,AQS維護了兩個對個隊列,一個是同步隊列,一個是阻塞隊列。

Node可以說是【同步隊列】和【阻塞隊列】的節(jié)點。

2.1 Node源碼剖析

  static final class Node {
    // 模式,分為共享與獨占
    // 共享模式
    static final Node SHARED = new Node();
    // 獨占模式
    static final Node EXCLUSIVE = null;        
    // 結(jié)點狀態(tài)
    // CANCELLED,值為1,表示當前的線程被取消
    // SIGNAL,值為-1,表示當前節(jié)點的后繼節(jié)點包含的線程需要運行,也就是unpark
    // CONDITION,值為-2,表示當前節(jié)點在等待condition,也就是在condition隊列中
    // PROPAGATE,值為-3,表示當前場景下后續(xù)的acquireShared能夠得以執(zhí)行
    static final int CANCELLED =  1;
    static final int SIGNAL    = -1;
    static final int CONDITION = -2;
    static final int PROPAGATE = -3;        

    // 結(jié)點狀態(tài)
    volatile int waitStatus;        
    // 前驅(qū)結(jié)點
    volatile Node prev;    
    // 后繼結(jié)點
    volatile Node next;        
    // 結(jié)點所對應(yīng)的線程
    volatile Thread thread;        
    // 下一個等待者
    Node nextWaiter;
    
    // 結(jié)點是否在共享模式下等待
    final boolean isShared() {
        return nextWaiter == SHARED;
    }
    
    // 獲取前驅(qū)結(jié)點,若前驅(qū)結(jié)點為空,拋出異常
    final Node predecessor() throws NullPointerException {
        // 保存前驅(qū)結(jié)點
        Node p = prev; 
        if (p == null) // 前驅(qū)結(jié)點為空,拋出異常
            throw new NullPointerException();
        else // 前驅(qū)結(jié)點不為空,返回
            return p;
    }
    
    // 無參構(gòu)造函數(shù)
    Node() {    // Used to establish initial head or SHARED marker
    }
    
    // 構(gòu)造函數(shù),被addWaiter使用
     Node(Thread thread, Node mode) {    // Used by addWaiter
        this.nextWaiter = mode;
        this.thread = thread;
    }
    
    // 構(gòu)造函數(shù)
    Node(Thread thread, int waitStatus) { // Used by Condition
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

2.2 ConditionObject源碼剖析

實現(xiàn)了condition接口,關(guān)于condition的學(xué)習(xí)后面會介紹,在學(xué)習(xí)ReentrantLock時也介紹了其使用方式。

代碼較多,直接從上向下看吧:

 // 內(nèi)部類
public class ConditionObject implements Condition, java.io.Serializable {
    // 版本號
    private static final long serialVersionUID = 1173984872572414699L;
    
    // condition隊列的頭結(jié)點
    private transient Node firstWaiter;
    
    // condition隊列的尾結(jié)點
    private transient Node lastWaiter;

    /**
     *  構(gòu)造函數(shù)
     */
    public ConditionObject() { }

    /**
     * 添加新的waiter到wait隊列
     */
    private Node addConditionWaiter() {
        // 定義尾結(jié)點是t
        Node t = lastWaiter;
       // 尾結(jié)點不為空,并且尾結(jié)點的狀態(tài)不為CONDITION(默認是-2,表示當前節(jié)點在conditionObject等待隊列中)
        if (t != null && t.waitStatus != Node.CONDITION) { 
            // 清除狀態(tài)不為CONDITION的結(jié)點,對firstWaiter和lastWaiter重新賦值
            unlinkCancelledWaiters(); 
            // 將最后一個結(jié)點重新賦值給t
            t = lastWaiter;
        }
        // 新建一個結(jié)點
        Node node = new Node(Thread.currentThread(), Node.CONDITION);
        // 尾結(jié)點為空
        if (t == null) 
            // 設(shè)置condition隊列的頭結(jié)點
            firstWaiter = node;
        else 
            // 設(shè)置為節(jié)點的nextWaiter域為node結(jié)點
            t.nextWaiter = node;
        // 更新condition隊列的尾結(jié)點
        lastWaiter = node;
        return node;
    }

    /**
     *  移除或轉(zhuǎn)移頭結(jié)點到sync隊列,直到?jīng)]有取消的或者空為止
     */
    private void doSignal(Node first) {
        // 循環(huán)
        do {
            // 將下一個節(jié)點設(shè)為首節(jié)點,如果為空
            if ( (firstWaiter = first.nextWaiter) == null) 
                // 設(shè)置尾結(jié)點為空
                lastWaiter = null;
            // 設(shè)置first結(jié)點的nextWaiter域
            first.nextWaiter = null;
        } while (!transferForSignal(first) &&
                 (first = firstWaiter) != null); // 將結(jié)點從condition隊列轉(zhuǎn)移到sync隊列失敗并且condition隊列中的頭結(jié)點不為空,一直循環(huán)
    }

    /**
     * 轉(zhuǎn)移所有等待隊列的節(jié)點到同步隊列
     */
    private void doSignalAll(Node first) {
        // condition隊列的頭結(jié)點尾結(jié)點都設(shè)置為空
        lastWaiter = firstWaiter = null;
        // 循環(huán)
        do {
            // 獲取first結(jié)點的nextWaiter域結(jié)點
            Node next = first.nextWaiter;
            // 設(shè)置first結(jié)點的nextWaiter域為空
            first.nextWaiter = null;
            // 將first結(jié)點從condition隊列轉(zhuǎn)移到sync隊列
            transferForSignal(first);
            // 重新設(shè)置first
            first = next;
        } while (first != null);
    }

    /**
     * 過濾掉狀態(tài)不為CONDITION的節(jié)點
     * 對firstWaiter和lastWaiter重新賦值
     **/
    private void unlinkCancelledWaiters() {
        // 獲取condition隊列頭結(jié)點
        Node t = firstWaiter;
        // 獲取一個尾結(jié)點是null
        Node trail = null;
        while (t != null) {
            // 獲取下一個結(jié)點
            Node next = t.nextWaiter;
            // 頭結(jié)點的狀態(tài)不為CONDTION狀態(tài)
            if (t.waitStatus != Node.CONDITION) { 
                // 設(shè)置t節(jié)點的下一個等待者為空
                t.nextWaiter = null;
                if (trail == null) // trail為空,首次進來一定為空
                    // 重新設(shè)置condition隊列的頭結(jié)點
                    firstWaiter = next;
                else 
                    // 設(shè)置trail結(jié)點的nextWaiter域為next結(jié)點
                    trail.nextWaiter = next;
                if (next == null) // next結(jié)點為空
                    // 設(shè)置condition隊列的尾結(jié)點
                    lastWaiter = trail;
            }
            else // t結(jié)點的狀態(tài)為CONDTION狀態(tài)
                // 設(shè)置trail結(jié)點
                trail = t;
            // 設(shè)置t結(jié)點
            t = next;
        }
    }

    /**
     * 實現(xiàn)Condition接口的signal方法
     */
    public final void signal() {
        if (!isHeldExclusively()) // 不被當前線程獨占,拋出異常
            throw new IllegalMonitorStateException();
        // 保存condition隊列頭結(jié)點
        Node first = firstWaiter;
        if (first != null) // 頭結(jié)點不為空
            // 喚醒一個等待線程,將頭結(jié)點從阻塞隊列移除,添加到同步隊列
            doSignal(first);
    }

    /**
     * 實現(xiàn)Condition的signalAll方法,喚醒所有線程
     */
    public final void signalAll() {
        if (!isHeldExclusively()) // 不被當前線程獨占,拋出異常
            throw new IllegalMonitorStateException();
        // 保存condition隊列頭結(jié)點
        Node first = firstWaiter;
        if (first != null) // 頭結(jié)點不為空
            // 喚醒所有等待線程,將頭結(jié)點從阻塞隊列移除,添加到同步隊列
            doSignalAll(first);
    }

    /**
     * 與await()區(qū)別在于,使用await方法,調(diào)用interrupt()中斷后會報錯,而該方法不會報錯。
     */
    public final void awaitUninterruptibly() {
        // 添加一個結(jié)點到等待隊列
        Node node = addConditionWaiter();
        // 獲取釋放的狀態(tài)
        int savedState = fullyRelease(node);
        boolean interrupted = false;
        while (!isOnSyncQueue(node)) { // 
            // 阻塞當前線程
            LockSupport.park(this);
            if (Thread.interrupted()) // 當前線程被中斷
                // 設(shè)置interrupted狀態(tài)
                interrupted = true; 
        }
        if (acquireQueued(node, savedState) || interrupted) // 
            selfInterrupt();
    }

    /**
     *  等待,當前線程在接到信號或被中斷之前一直處于等待狀態(tài)
     */
    public final void await() throws InterruptedException {
        // 當前線程被中斷,拋出異常
        if (Thread.interrupted()) 
            throw new InterruptedException();
        // 將當前線程包裝成Node,尾插入到等待隊列中
        Node node = addConditionWaiter();
        // 釋放當前線程所占用的lock,在釋放的過程中會喚醒同步隊列中的下一個節(jié)點
        int savedState = fullyRelease(node);
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            // 當前線程進入到等待狀態(tài)
            LockSupport.park(this);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) // 檢查結(jié)點等待時的中斷類型
                break;
        }
        // 自旋等待獲取到同步狀態(tài)(即獲取到lock)
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null) // clean up if cancelled
            unlinkCancelledWaiters();
        // 處理被中斷的情況
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
    }

    /**
     * 等待,當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態(tài)
     */
    public final long awaitNanos(long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return deadline - System.nanoTime();
    }

    /**
     * 等待,當前線程在接到信號、被中斷或到達指定最后期限之前一直處于等待狀態(tài)
     */
    public final boolean awaitUntil(Date deadline)
            throws InterruptedException {
        long abstime = deadline.getTime();
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (System.currentTimeMillis() > abstime) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            LockSupport.parkUntil(this, abstime);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

    /**
     * 等待,當前線程在接到信號、被中斷或到達指定等待時間之前一直處于等待狀態(tài)。此方法在行為上等              
     * 效于:awaitNanos(unit.toNanos(time)) > 0
     */
    public final boolean await(long time, TimeUnit unit)
            throws InterruptedException {
        long nanosTimeout = unit.toNanos(time);
        if (Thread.interrupted())
            throw new InterruptedException();
        // 1. 將當前線程包裝成Node,尾插入到等待隊列中
        Node node = addConditionWaiter();
        // 2. 釋放當前線程所占用的lock,在釋放的過程中會喚醒同步隊列中的下一個節(jié)點
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

2.3 鎖的獲取和釋放

整個AQS的設(shè)計理念就是通過state字段來實現(xiàn)鎖的獲取和釋放,鎖有主要分為公平鎖和非公平鎖。

2.3.1 公平鎖

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            // 繼承自AQS的方法,內(nèi)部先調(diào)用tryAcquire獲取鎖,獲取失敗則添加下城到等待隊列當中
            acquire(1);
        }

        /**
         * 公平鎖版本的tryAcquire
         */
        protected final boolean tryAcquire(int acquires) {
            // 獲取當前線程
            final Thread current = Thread.currentThread();
            // 獲取鎖的狀態(tài)
            int c = getState();
            // 0表示鎖沒有被持有
            if (c == 0) {
                // 判斷當前等待隊列是否有節(jié)點在等待,沒有才去競爭
                if (!hasQueuedPredecessors() &&
                    // 比較并替換狀態(tài)
                    compareAndSetState(0, acquires)) {
                    // 設(shè)置當前線程為獨占線程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                // 此處表示鎖重入
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

2.3.2 非公平鎖

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * 立即獲取鎖,失敗會加入等待隊列
         */
        final void lock() {
            // 通過CAS嘗試獲取鎖,成功則設(shè)置當前線程獨占
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                // 否則加入等待隊列·····································································································································
                acquire(1);
        }

        /** 
          * 非公平鎖版本的tryAcquire
          */
        protected final boolean tryAcquire(int acquires) {
            // 走其父類Sync的默認nonfairTryAcquire
            return nonfairTryAcquire(acquires);
        }
    }

2.3.3 Syc子類

這是公平鎖和非公平鎖的父類,提供統(tǒng)一的tryRelease方法釋放鎖

    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 提供非公平版本的快捷路徑
         */
        abstract void lock();

        /**
         * 非公平鎖獲取,默認就是非公平鎖
         */
        final boolean nonfairTryAcquire(int acquires) {
            // 獲取當前線程
            final Thread current = Thread.currentThread();
            // 獲取當前鎖的狀態(tài)
            int c = getState();
            // 0表示沒有被占用
            if (c == 0) {
                // CAS占用,成功則設(shè)置當前線程為獨占鎖
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 當前線程是獨占鎖,表示鎖重入
            else if (current == getExclusiveOwnerThread()) {
                // 狀態(tài) + 1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                // 設(shè)置當前狀態(tài)
                setState(nextc);
                return true;
            }
            return false;
        }

         /**
         * 釋放鎖
         */
        protected final boolean tryRelease(int releases) {
            // 當前狀態(tài) 減去 釋放的數(shù)量
            int c = getState() - releases;
            // 如果當前線程不是占有鎖的線程,拋出異常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            // 當全部釋放后,狀態(tài)為0,取消獨占線程
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            // 設(shè)置狀態(tài)為0,返回釋放成功
            setState(c);
            return free;
        }

        protected final boolean isHeldExclusively() {
            // 當前線程是否是鎖持有者
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        // 獲取當前持有者
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        // 獲取持有數(shù),只有是線程持有者才能獲取
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }
    }

3.3.4 acquire 和 release

在AQS當中還有兩個核心方法:

  • acquire():獲取鎖,這是實際鎖調(diào)用上鎖的真正方法,前面的try開頭的知識嘗試獲取鎖,即使失敗也不會添加到等待隊列。
    public final void acquire(int arg) {
      // 嘗試獲取
      if (!tryAcquire(arg) &&
          // 嘗試獲取成功,以獨占方式添加到等待隊列,并不斷地嘗試占有鎖知道成功
          acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
          selfInterrupt();
  }
  • release():釋放鎖,這是實際釋放鎖的方法,會調(diào)用鎖自定義的同步器實現(xiàn)的tryRelease方法:
        /**
          * 嘗試釋放,成功后返回true
          */
        public final boolean release(int arg) {
          if (tryRelease(arg)) {
              Node h = head;
              if (h != null && h.waitStatus != 0)
                  unparkSuccessor(h);
              return true;
          }
          return false;
      }
    

后面我們自定義不可重入鎖,來看看同步器和鎖的關(guān)系是什么樣的,加深理解。

2.4 簡單總結(jié)

到此為止,通過閱讀前面的源碼內(nèi)容,我們可以有如下的總結(jié):

  • 鎖的釋放和獲取都是圍繞 【state】來做的,0表示未持有鎖,1表示獨占,大于一表示鎖重入
  • 獲取鎖的姿勢如下:
      // 如果獲取鎖失敗
      if (!tryAcquire(arg)) {
        // 入隊, 可以選擇阻塞當前線程 park unpark
      }
    
  • 釋放鎖的姿勢如下:
      // 如果獲取鎖成功
      if (!tryRelease(arg)) {
        // 讓阻塞線程恢復(fù)運行
      }
    

三、實踐

了解了AQS的結(jié)構(gòu)之后,我們不妨自己動手實踐一番。加深理解。

定義一個不可重入鎖,需要一個同步器,一個鎖,一個測試類

自定義同步器:

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * @description: 實現(xiàn)一個不可重入鎖 同步器,state最大只能是1
 * @author:weirx
 * @date:2022/1/13 13:49
 * @version:3.0
 */
public class MyLockSynchronizer extends AbstractQueuedSynchronizer {

    @Override
    protected boolean tryAcquire(int acquires) {
        int state = getState();
        if (state == 0) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
        }
        return false;
    }

    @Override
    protected boolean tryRelease(int acquires) {
        int c = getState() - acquires;
        if (c == 0) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        return false;
    }

    @Override
    protected boolean isHeldExclusively() {
        return getState() == 1;
    }

    protected ConditionObject newCondition() {
        return new ConditionObject();
    }
}

自定義鎖:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @description: 自定義鎖
 * @author:weirx
 * @date:2022/1/13 14:05
 * @version:3.0
 */
public class MyLock implements Lock {

    MyLockSynchronizer myLockSynchronizer = new MyLockSynchronizer();

    @Override
    public void lock() {
        // 嘗試獲取鎖,失敗則加入等待隊列
        myLockSynchronizer.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        // 嘗試獲取鎖,失敗則加入等待隊列, 可中斷
        myLockSynchronizer.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        // 嘗試獲取鎖,不加入等待隊列
        return myLockSynchronizer.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        // 嘗試獲取鎖,不加入等待隊列,有實現(xiàn)
        return myLockSynchronizer.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        // 釋放鎖
        myLockSynchronizer.release(1);
    }

    @Override
    public Condition newCondition() {
        // 條件變量
        return myLockSynchronizer.newCondition();
    }
}

測試鎖的效果:

/**
 * @description: 測試
 * @author:weirx
 * @date:2022/1/13 14:24
 * @version:3.0
 */
public class TestMyLock {

    public static void main(String[] args) {
        MyLock myLock = new MyLock();

        new Thread(() -> {
            try {
                myLock.lock();
                System.out.println(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")
                        + " " + Thread.currentThread().getName() + " :acquire lock success");

                // 休眠一秒看效果
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                myLock.unlock();
                System.out.println(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")
                        + " " + Thread.currentThread().getName() + " :release lock success");
            }

        }, "t1").start();

        new Thread(() -> {
            try {
                myLock.lock();
                System.out.println(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")
                        + " " + Thread.currentThread().getName() + " :acquire lock success");
            } finally {
                myLock.unlock();
                System.out.println(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")
                        + " " + Thread.currentThread().getName() + " :release lock success");
            }
        }, "t2").start();
    }
}

結(jié)果,ti一秒后釋放鎖,才會由t2獲得鎖:

2022-01-13 14:34:56 t1 :acquire lock success
2022-01-13 14:34:57 t2 :acquire lock success
2022-01-13 14:34:57 t1 :release lock success
2022-01-13 14:34:57 t2 :release lock success

測試下不可重入是否好使,只需要在上述測試代碼的線程t1中,再次使用myLock.lock()獲取一次鎖,發(fā)現(xiàn),整個程序被卡住了,只會打印一條信息:

2022-01-13 14:35:56 t1 :acquire lock success

四、關(guān)于Condition的補充

本篇沒有介紹Condition的具體內(nèi)容,但是在之前講解ReentrantLock提到過【條件變量】,可以返回去看這篇文章了解其用法:http://www.itdecent.cn/p/edec5185196d


源碼學(xué)習(xí)真是難,看別人說的再多不如自己跟著走一遍,建議同學(xué)們參照本文自己跟蹤一遍。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容