1. 程式人生 > >ReentrantLock 原始碼分析

ReentrantLock 原始碼分析

ReentrantLock

1)ReentrantLock 類實現了和 synchronized 一樣的記憶體語義,同時該類提供了更加靈活多樣的可重入互斥鎖定操作。
2)ReentrantLock 例項可以被同一個執行緒多次獲取,因此是可重入的互斥鎖。

例項建立

    /**
     * 建立一個非公平的可重入互斥鎖例項
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    /**
     * fair=true:建立一個公平的可重入互斥鎖例項,誰先加入同步佇列誰先獲取鎖。
     * fair=false:建立一個非公平的可重入互斥鎖例項
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

讀取鎖【非公平鎖】

    /**
      * 1)如果該可重入互斥鎖沒有被另一個執行緒保持,則獲取該可重入互斥鎖並立即返回,
      * 將可重入互斥鎖的保持計數設定為 1。
      * 2)如果當前執行緒已經持有該可重入互斥鎖,則將保持計數加 1,並且該方法立即返回。
      * 3)如果該可重入互斥鎖被另一個執行緒保持,當前執行緒將阻塞等待獲取可重入互斥鎖。
      */
    public void lock() {
        sync.acquire(1);
    }

AbstractQueuedSynchronizer#acquire
    /**
     * 1)在獨佔模式下獲取鎖,忽略中斷【執行緒被中斷後,當嘗試獲取鎖時會被清除中斷狀態並重新進入阻塞模式】
     * 2)首先嚐試進行一次鎖獲取,如果獲取成功則直接返回;
     * 如果獲取失敗,則將當前執行緒加入同步佇列中阻塞等待獲取鎖。
     */
    public final void acquire(int arg) {
        /**
         * 1)tryAcquire 首先嚐試獲取鎖,獲取成功則直接返回
         * 2)獲取失敗後,通過 addWaiter 建立一個獨佔模式的節點,
         * 並將當前執行緒駐留其上,通過 acquireQueued 將該節點加入同步佇列阻塞等待獲取鎖。
         * 3)如果嘗試獲取鎖時執行緒被設定了中斷標識,則當期執行緒中斷自己。
         */
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
            AbstractQueuedSynchronizer.selfInterrupt();
        }
    }

    /**
     * 非公平鎖的同步物件
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        protected boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    /**
     * ReentrantLock 鎖的同步控制基礎類
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 非公平地嘗試獲取鎖操作
         */
        @ReservedStackAccess
        final boolean nonfairTryAcquire(int acquires) {
            // 讀取當前執行緒
            final Thread current = Thread.currentThread();
            // 讀取同步狀態值
            final int c = getState();
            // 1)如果同步狀態為 0,表示沒有執行緒持有鎖
            if (c == 0) {
                // 嘗試原子更新同步狀態為 acquires,此處是 1
                if (compareAndSetState(0, acquires)) {
                    // 如果設定成功,則表示當前執行緒獲取鎖成功,則設定同步器的獨佔執行緒為當前執行緒
                    setExclusiveOwnerThread(current);
                    // 成功獲取鎖返回 true
                    return true;
                }
            }
            // 2)判斷持有鎖的執行緒是否是當前執行緒
            else if (current == getExclusiveOwnerThread()) {
                // 如果是當前執行緒,則表示鎖重入,遞增同步狀態值
                final int nextc = c + acquires;
                // 同步狀態值溢位
                if (nextc < 0) {
                    throw new Error("Maximum lock count exceeded");
                }
                // 更新同步狀態值
                setState(nextc);
                // 成功獲取鎖返回 true
                return true;
            }
            // 鎖已經被其他執行緒持有,獲取失敗則 false
            return false;
        }
    }

AbstractQueuedSynchronizer#Node
    /**
     * 同步器佇列節點
     */
    static final class Node {
        /** 標識當前節點在共享模式下等待 */
        static final Node SHARED = new Node();
        /** 標識當前節點在獨佔模式下等待 */
        static final Node EXCLUSIVE = null;

        /** 節點駐留執行緒由於超時或被中斷而取消 */
        static final int CANCELLED =  1;
        /** 後繼節點的駐留執行緒需要在當前節點被釋放之後,被喚醒 */
        static final int SIGNAL    = -1;
        /** 當前執行緒在條件佇列中等待 */
        static final int CONDITION = -2;
        /**
         * 下一次 acquireShared 操作需要被無條件往後傳播,用於鎖共享模式下
         */
        static final int PROPAGATE = -3;

        /**
         * 同步器狀態值
         *   SIGNAL: 當前節點的後繼節點上駐留的執行緒被阻塞,當前節點被釋放或取消時,
         *      必須喚醒其後繼節點上駐留的執行緒。
         *   CANCELLED: 當前節點由於超時或執行緒被中斷而取消,節點永遠不會離開該狀態,
         *      被取消的節點不會再次阻塞。
         *   CONDITION: 當前節點位於條件佇列,當滿足條件時,該節點的同步狀態會被設定為 0,
         *      並轉移到同步佇列中。
         *   PROPAGATE: releaseShared 操作需要被無條件向後傳播,該值只能設定在頭節點上。
         *   0: 同步佇列節點的初始狀態。
         *
         * 非負值表示節點不需要訊號【節點被取消】,在某些場景下可以簡化使用。
         * 同步佇列節點的初始同步狀態為 0,條件佇列節點的初始同步狀態為 -2.
         */
        volatile int waitStatus;

        /**
         * 同步佇列節點的前置節點,在入佇列時設定,在出佇列時設定為 null.
         */
        volatile Node prev;

        /**
         * 同步佇列節點的後置節點,在繞過取消的節點時更新,在節點出佇列時置為 null。
         * 被取消節點的 next 值被設定為節點本身。
         */
        volatile Node next;

        /**
         * 駐留在節點的執行緒,在建立時設定,在使用後置為 null。
         */
        volatile Thread thread;

        /**
         * 1)條件佇列只在獨佔模式下被訪問,nextWaiter 值為下一個在條件上等待的節點。
         * 2)如果值為 SHARED,則表示該節點處於共享模式。
         */
        Node nextWaiter;

        /**
         * 節點處於共享模式,則返回 true
         */
        boolean isShared() {
            return nextWaiter == Node.SHARED;
        }

        /**
         * 讀取當前節點的前置節點
         */
        Node predecessor() {
            final Node p = prev;
            if (p == null) {
                throw new NullPointerException();
            } else {
                return p;
            }
        }

        /** Establishes initial head or SHARED marker. */
        Node() {}

        /** Constructor used by addWaiter. */
        Node(Node nextWaiter) {
            // 設定下一個等待節點
            this.nextWaiter = nextWaiter;
            // 將當期執行緒駐留其上
            Node.THREAD.set(this, Thread.currentThread());
        }

        /** Constructor used by addConditionWaiter. */
        Node(int waitStatus) {
            Node.WAITSTATUS.set(this, waitStatus);
            Node.THREAD.set(this, Thread.currentThread());
        }

        /** 嘗試更新同步狀態 */
        boolean compareAndSetWaitStatus(int expect, int update) {
            return Node.WAITSTATUS.compareAndSet(this, expect, update);
        }

        /** 嘗試更新當前節點的後置節點 */
        boolean compareAndSetNext(Node expect, Node update) {
            return Node.NEXT.compareAndSet(this, expect, update);
        }

        // 設定當前節點的前置節點
        void setPrevRelaxed(Node p) {
            Node.PREV.set(this, p);
        }

        // VarHandle mechanics
        private static final VarHandle NEXT;
        private static final VarHandle PREV;
        private static final VarHandle THREAD;
        private static final VarHandle WAITSTATUS;
        static {
            try {
                final MethodHandles.Lookup l = MethodHandles.lookup();
                NEXT = l.findVarHandle(Node.class, "next", Node.class);
                PREV = l.findVarHandle(Node.class, "prev", Node.class);
                THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
                WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
            } catch (final ReflectiveOperationException e) {
                throw new Error(e);
            }
        }
    }

AbstractQueuedSynchronizer#addWaiter
    /**
     * 以指定的模式 mode 建立節點,並將當前執行緒駐留其上,之後將該節點加入同步佇列。
     */
    private Node addWaiter(Node mode) {
        // 建立節點並駐留當前執行緒
        final Node node = new Node(mode);

        for (;;) {
            // 讀取尾節點
            final Node oldTail = tail;
            // 1)尾節點不為 null,則直接將該節點加入到同步佇列尾部
            if (oldTail != null) {
                // 設定前置節點
                node.setPrevRelaxed(oldTail);
                // 比較設定尾部節點
                if (compareAndSetTail(oldTail, node)) {
                    // 設定成功,則更新舊尾節點的 next 為當前節點【新尾節點】
                    oldTail.next = node;
                    // 返回當前節點
                    return node;
                }
                // 2)初始化同步佇列
            } else {
                initializeSyncQueue();
            }
        }
    }

AbstractQueuedSynchronizer#initializeSyncQueue
    /**
     * 在第一次發生鎖競爭時初始化同步佇列的頭、尾節點,
     * 同步佇列的頭節點是一個傀儡節點,不駐留執行緒,新建時同步狀態為 0,
     * 阻塞節點加入佇列後,同步狀態被設定為 -1.
     */
    private final void initializeSyncQueue() {
        Node h;
        // 原子設定頭結點為新建節點
        if (AbstractQueuedSynchronizer.HEAD.compareAndSet(this, null, h = new Node())) {
            // 設定為節點為新建節點
            tail = h;
        }
    }

AbstractQueuedSynchronizer#acquireQueued
    /**
     * 在獨佔、執行緒不可中斷的模式下獲取鎖,當前執行緒已經在同步佇列中。
     */
    final boolean acquireQueued(final Node node, int arg) {
        boolean interrupted = false;
        try {
            for (;;) {
                // 讀取當前節點的前置節點
                final Node p = node.predecessor();
                // 如果前置節點是 head,則嘗試獲取鎖
                if (p == head && tryAcquire(arg)) {
                    // 獲取成功,則設定當前節點為 head
                    setHead(node);
                    p.next = null; // help GC
                    // 返回執行緒中斷標識
                    return interrupted;
                }
                // 當前執行緒是否需要被阻塞
                if (AbstractQueuedSynchronizer.shouldParkAfterFailedAcquire(p, node)) {
                    // 阻塞當前執行緒,並等待喚醒,喚醒後返回其中斷狀態
                    interrupted |= parkAndCheckInterrupt();
                }
            }
        // 執行緒執行過程中出現異常  
        } catch (final Throwable t) {
            // 取消當前節點
            cancelAcquire(node);
            // 如果執行緒被設定中斷標識
            if (interrupted) {
                // 則執行緒自我中斷
                AbstractQueuedSynchronizer.selfInterrupt();
            }
            throw t;
        }
    }

AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire
    /**
     * 判斷並更新前置節點的狀態,如果執行緒需要被阻塞,則返回 true
     */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        // 讀取前置節點的同步狀態
        final int ws = pred.waitStatus;
        // 1)前置節點已經是 Node.SIGNAL,最後入隊的節點被取消而踢除時出現。
        if (ws == Node.SIGNAL) {
            // 當前執行緒需要被阻塞,則返回 true
            return true;
        }
        // 2)前置節點已經被取消
        if (ws > 0) {
            // 將被取消的前置節點踢除,直到遇到一個需要訊號的節點為止
            do {
                // 踢除前置節點
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            // 將當前節點連結到新的前置節點後
            pred.next = node;
        } else {
            /**
             * waitStatus must be 0 or PROPAGATE.
             * 將前置節點設定為 Node.SIGNAL,表示當前置節點被釋放時,需要喚醒當前節點
             * 再次獲取鎖失敗時,當前節點將阻塞等待。
             */
            pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
        }
        // 執行緒不需要被阻塞,再次嘗試獲取鎖
        return false;
    }

AbstractQueuedSynchronizer#parkAndCheckInterrupt
    /**
     * 阻塞當前執行緒,並在執行緒被釋放時【正常釋放或被其他執行緒中斷】
     * 返回中斷狀態。
     */
    private final boolean parkAndCheckInterrupt() {
        // 阻塞當前執行緒
        LockSupport.park(this);
        // 返回並清除執行緒中斷狀態
        return Thread.interrupted();
    }

LockSupport#park
    /**
     * 在許可可用之前阻塞當前執行緒。
     * 如果許可可用,則使用該許可,並且該呼叫立即返回;否則,當前執行緒將被阻塞。
     * 以下場景下該方法呼叫才會返回:
     * 1)其他某個執行緒呼叫將當前執行緒作為目標呼叫 unpark。
     * 2)其他某個執行緒中斷當前執行緒。
     * 3)該呼叫不合邏輯地(即毫無理由地)返回。
     */
    public static void park(Object blocker) {
        // 讀取當前執行緒
        Thread t = Thread.currentThread();
        // 設定 Thread 的 parkBlocker 屬性為阻塞者 blocker
        setBlocker(t, blocker);
        // 阻塞當前執行緒
        U.park(false, 0L);
        // 執行緒被重新排程,則置空當前執行緒的 parkBlocker
        setBlocker(t, null);
    }

Unsafe#park
    /**
     * 阻塞當前執行緒
     * 1)isAbsolute=false,time=0:直到其他執行緒呼叫 LockSupport#unpark 方法喚醒
     * 目標執行緒,或目標執行緒被其他執行緒中斷。
     * 2)isAbsolute=false,time>0:除了執行緒被主動喚醒、執行緒被中斷之外,指定的納秒時間已經過去
     * ,則執行緒被自動喚醒。
     * 3)isAbsolute=true,time>0:除了執行緒被主動喚醒、執行緒被中斷之外,
     * 當前時間已經超過指定 Epoch 的時間戳,則執行緒被自動喚醒。
     * 4)異常情況下被喚醒
     */
    @HotSpotIntrinsicCandidate
    public native void park(boolean isAbsolute, long time);

AbstractQueuedSynchronizer#cancelAcquire
    /**
     * 1)被取消節點是尾節點,則直接踢除
     * 2)被取消節點是第一個需要獲取鎖的節點,則喚醒其後置節點
     * 3)被取消節點在中間,則將前置節點和後置節點相連
     * 取消正在進行的獲取鎖操作
     */
    private void cancelAcquire(Node node) {
        // 節點已經不存在,則直接返回
        if (node == null) {
            return;
        }
        
        // 清除節點駐留執行緒
        node.thread = null;

        // 跳過被取消的前置節點
        Node pred = node.prev;
        while (pred.waitStatus > 0) {
            node.prev = pred = pred.prev;
        }

        // predNext is the apparent node to unsplice. CASes below will
        // fail if not, in which case, we lost race vs another cancel
        // or signal, so no further action is necessary.
        final Node predNext = pred.next;

        // 設定節點的同步狀態為已經取消
        node.waitStatus = Node.CANCELLED;

        // 1)當前節點是尾節點,則比較更新尾部接地啊
        if (node == tail && compareAndSetTail(node, pred)) {
            // 尾部節點更新成功後,比較更新尾節點的 next 屬性
            pred.compareAndSetNext(predNext, null);
        // 2)當前節點不是尾節點
        } else {
            /**
             * 1)前置節點不是頭節點,並且前置節點的同步狀態為 Node.SIGNAL【
             * 如果同步狀態<=0,則將其設定為 Node.SIGNAL】,
             * 並且前置節點的駐留執行緒不為 null【不是傀儡節點】。
             */
            int ws;
            if (pred != head &&
                    ((ws = pred.waitStatus) == Node.SIGNAL ||
                    ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL)) &&
                    pred.thread != null) {
                // 讀取後置節點
                final Node next = node.next;
                // 後置節點不為 null,並且其需要訊號
                if (next != null && next.waitStatus <= 0) {
                    // 則比較更新前置節點的 next 屬性
                    pred.compareAndSetNext(predNext, next);
                }
            /**
             * 2)前置節點是頭節點,說明當前節點是需要獲取鎖的第一個節點,
             * 當前節點被取消,需要喚醒其後繼節點。   
             */
            } else {
                unparkSuccessor(node);
            }
            // 被取消節點的 next 設定為節點本身
            node.next = node; // help GC
        }
    }

AbstractQueuedSynchronizer#unparkSuccessor
    /**
     * 如果後繼節點存在,則喚醒駐留其上的執行緒
     */
    private void unparkSuccessor(Node node) {
        // 讀取節點同步狀態
        final int ws = node.waitStatus;
        // 節點需要訊號,則比較更新為 0
        if (ws < 0) {
            node.compareAndSetWaitStatus(ws, 0);
        }

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        /**
         * 讀取後置節點
         */
        Node s = node.next;
        // 後置節點為 null 或後置節點已經被取消
        if (s == null || s.waitStatus > 0) {
            s = null;
            /**
             * 從尾部開始遍歷,如果迭代節點不是當前節點,並且其不為 null,則進入迴圈體。
             * 一旦遇到當前節點或前置節點為 null【遍歷到頭部】,則退出迴圈。
             * 遍歷完成之後,可以獲取到當前節點後,第一個需要被喚醒的節點【如果存在】
             */
            for (Node p = tail; p != node && p != null; p = p.prev) {
                // 迭代節點需要訊號
                if (p.waitStatus <= 0) {
                    // 則更新需要被喚醒的節點
                    s = p;
                }
            }
        }
        // 目標節點存在
        if (s != null) {
            // 則喚醒駐留其上的執行緒
            LockSupport.unpark(s.thread);
        }
    }

LockSupport#unpark
    /**
     * 給當前執行緒一個許可,如果當前執行緒被阻塞,則將其喚醒;
     * 如果執行緒已經被喚醒,則下一次呼叫 park 操作形參 Thread 將不會被阻塞。
     */
    public static void unpark(Thread thread) {
        if (thread != null) {
            // 喚醒目標執行緒
            LockSupport.U.unpark(thread);
        }
    }

獲取鎖【公平鎖】

    /**
     * 1)如果該可重入互斥鎖沒有被另一個執行緒保持,則獲取該可重入互斥鎖並立即返回,
     * 將可重入互斥鎖的保持計數設定為 1。
     * 2)如果當前執行緒已經持有該可重入互斥鎖,則將保持計數加 1,並且該方法立即返回。
     * 3)如果該可重入互斥鎖被另一個執行緒保持,當前執行緒將阻塞等待獲取可重入互斥鎖。
     */
    @Override
    public void lock() {
        sync.acquire(1);
    }

AbstractQueuedSynchronizer#acquire
    /**
     * 1)在獨佔模式下獲取鎖,忽略中斷【執行緒被中斷後,當嘗試獲取鎖時會被清除中斷狀態並重新進入阻塞模式】
     * 2)首先嚐試進行一次鎖獲取,如果獲取成功則直接返回;
     * 如果獲取失敗,則將當前執行緒加入同步佇列中阻塞等待獲取鎖。
     */
    public final void acquire(int arg) {
        /**
         * 1)tryAcquire 首先嚐試獲取鎖,獲取成功則直接返回
         * 2)獲取失敗後,通過 addWaiter 建立一個獨佔模式的節點,
         * 並將當前執行緒駐留其上,通過 acquireQueued 將該節點加入同步佇列阻塞等待獲取鎖。
         * 3)如果嘗試獲取鎖時執行緒被設定了中斷標識,則當期執行緒中斷自己。
         */
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
            AbstractQueuedSynchronizer.selfInterrupt();
        }
    }

    /**
     * 公平鎖的同步物件
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
        /**
         * 公平鎖的獲取操作
         */
        @Override
        @ReservedStackAccess
        protected boolean tryAcquire(int acquires) {
            // 讀取當前執行緒
            final Thread current = Thread.currentThread();
            // 讀取同步狀態
            final int c = getState();
            // 1)同步狀態為 0
            if (c == 0) {
                /**
                 * 1)同步佇列中沒有等待獲取鎖的執行緒或等待執行緒就是當前執行緒,
                 * 則比較更新同步狀態。
                 */
                if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                    // 更新成功則表示獲取鎖成功,返回 true
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 2)當前執行緒是持有鎖的執行緒,鎖重入
            else if (current == getExclusiveOwnerThread()) {
                // 遞增同步狀態值
                final int nextc = c + acquires;
                if (nextc < 0) {
                    throw new Error("Maximum lock count exceeded");
                }
                // 更新同步狀態值,獲取成功返回 true
                setState(nextc);
                return true;
            }
            return false;
        }
    }

AbstractQueuedSynchronizer#hasQueuedPredecessors
    /**
     * 是否有執行緒在等待獲取鎖
     */
    public final boolean hasQueuedPredecessors() {
        // 讀取尾節點
        final Node t = tail; // Read fields in reverse initialization order
        // 讀取頭節點
        final Node h = head;
        Node s;
        /**
         * 同步佇列中存在等待節點,並且
         * 1)head.next==null,同步佇列初始化時,說明已經有節點正在加入到同步佇列中
         * 2)第一個等待獲取鎖的節點駐留執行緒不是當前執行緒【如果是當前執行緒,則可以重入】 
         */
        return h != t &&
                ((s = h.next) == null || s.thread != Thread.currentThread());
    }

釋放鎖【公平鎖和非公平鎖一致】

    /**
     * 嘗試釋放鎖
     */
    @Override
    public void unlock() {
        sync.release(1);
    }

AbstractQueuedSynchronizer#release
    /**
     * 在獨佔模式下釋放鎖
     */
    public final boolean release(int arg) {
        // 嘗試釋放鎖
        if (tryRelease(arg)) {
            // 讀取頭節點
            final Node h = head;
            // 頭結點的同步狀態不為 0,則喚醒其後置節點
            if (h != null && h.waitStatus != 0) {
                // 喚醒目標節點的後繼節點
                unparkSuccessor(h);
            }
            return true;
        }
        return false;
    }

Sync#tryRelease
        @Override
        @ReservedStackAccess
        protected final boolean tryRelease(int releases) {
            // 計算新的同步狀態值
            final int c = getState() - releases;
            // 當前執行緒不是持有鎖的執行緒
            if (Thread.currentThread() != getExclusiveOwnerThread()) {
                // 丟擲 IllegalMonitorStateException 異常
                throw new IllegalMonitorStateException();
            }
            boolean free = false;
            // 同步狀態值為 0,標識鎖已經沒有被執行緒持有
            if (c == 0) {
                free = true;
                // 清空鎖持有執行緒
                setExclusiveOwnerThread(null);
            }
            // 更新狀態值
            setState(c);
            return free;
        }

可中斷地獲取鎖

    /**
     * 可響應中斷地獲取鎖,一旦目標執行緒被其他中斷,則丟擲 InterruptedException 異常。
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

AbstractQueuedSynchronizer#acquireInterruptibly
    /**
     * 1)在獨佔模式下獲取鎖
     * 2)首先嚐試進行一次鎖獲取,如果獲取成功則直接返回;
     * 如果獲取失敗,則將當前執行緒加入同步佇列中阻塞等待獲取鎖。
     * 3)如果目標執行緒被其他執行緒中斷,則丟擲 InterruptedException 異常
     */
    public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        // 返回並清除當前執行緒的中斷標識,如果執行緒已經被中斷
        if (Thread.interrupted()) {
            // 直接丟擲 InterruptedException 異常
            throw new InterruptedException();
        }
        // 嘗試獲取鎖
        if (!tryAcquire(arg)) {
            // 獲取失敗,則可中斷地再次獲取鎖
            doAcquireInterruptibly(arg);
        }
    }

AbstractQueuedSynchronizer#doAcquireInterruptibly
    /**
     * 在獨佔模式下獲取鎖,可響應執行緒中斷
     */
    private void doAcquireInterruptibly(int arg)
            throws InterruptedException {
        final Node node = addWaiter(Node.EXCLUSIVE);
        try {
            for (;;) {
                // 讀取當前節點的前置節點
                final Node p = node.predecessor();
                // 如果前置節點是 head,則嘗試獲取鎖
                if (p == head && tryAcquire(arg)) {
                    // 獲取成功,則設定當前節點為 head
                    setHead(node);
                    p.next = null; // help GC
                    return;
                }
                // 當前執行緒是否需要被阻塞,如果需要,則阻塞當前執行緒,並等待喚醒,喚醒後返回其中斷狀態
                if (AbstractQueuedSynchronizer.shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt()) {
                    // 如果當前執行緒被其他執行緒中斷
                    throw new InterruptedException();
                }
            }
        } catch (final Throwable t) {
            // 取消正在獲取的鎖操作
            cancelAcquire(node);
            throw t;
        }
    }

嘗試獲取鎖

    /**
     * 嘗試進行一次獲取鎖操作
     */
    @Override
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

帶超時時間的鎖獲取

    /**
     * 在指定的時間內,嘗試獲取鎖,一旦超時,則直接返回結果。
     * 可響應執行緒中斷。
     */
    @Override
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        // 將目標時間轉換為納秒
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

AbstractQueuedSynchronizer#tryAcquireNanos
    /**
     * 在獨佔模式下嘗試獲取鎖,
     * 1)執行緒被中斷,則直接丟擲 InterruptedException 異常
     * 2)超出目標時間,則直接返回
     */
    public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        // 獲取並清除當前執行緒的中斷標識
        if (Thread.interrupted()) {
            throw new InterruptedException();
        }
        /**
         *  1)嘗試進行鎖獲取,成功則直接返回 true。
         *  2)獲取失敗,則基於指定的超時時間再次嘗試獲取鎖,直到超時為止。
         */
        return tryAcquire(arg) ||
                doAcquireNanos(arg, nanosTimeout);
    }

AbstractQueuedSynchronizer#doAcquireNanos
    /**
     * 在獨佔、超時模式下獲取鎖
     */
    private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        // 超時時間為負數,則直接返回獲取失敗
        if (nanosTimeout <= 0L) {
            return false;
        }
        // 計算結束時間
        final long deadline = System.nanoTime() + nanosTimeout;
        // 將當前執行緒加入到同步佇列
        final Node node = addWaiter(Node.EXCLUSIVE);
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    return true;
                }
                // 計算剩餘時間
                nanosTimeout = deadline - System.nanoTime();
                // 已經超時
                if (nanosTimeout <= 0L) {
                    // 取消當前執行緒的鎖獲取操作
                    cancelAcquire(node);
                    return false;
                }
                /**
                 * 當前執行緒是否需要被阻塞,
                 * 1)如果超時時間大於 1000 納秒,則阻塞當前執行緒。
                 * 2)否則進行自旋獲取鎖操作。
                 */
                if (AbstractQueuedSynchronizer.shouldParkAfterFailedAcquire(p, node) &&
                        nanosTimeout > AbstractQueuedSynchronizer.SPIN_FOR_TIMEOUT_THRESHOLD) {
                    // 最多阻塞當前執行緒 nanosTimeout 納秒
                    LockSupport.parkNanos(this, nanosTimeout);
                }
                // 當前執行緒是否被中斷
                if (Thread.interrupted()) {
                    throw new InterruptedException();
                }
            }
        } catch (final Throwable t) {
            cancelAcquire(node);
            throw t;
        }
    }

    /**
     * 在許可可用之前阻塞當前執行緒。
     * 如果許可可用,則使用該許可,並且該呼叫立即返回;否則,當前執行緒將被阻塞。
     * 以下場景下該方法呼叫才會返回:
     * 1)其他某個執行緒將當前執行緒作為目標呼叫 unpark。
     * 2)其他某個執行緒中斷當前執行緒。
     * 3)執行緒阻塞已經超出 nanos 納秒
     * 4)該呼叫不合邏輯地(即毫無理由地)返回。
     */
    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            final Thread t = Thread.currentThread();
            LockSupport.setBlocker(t, blocker);
            LockSupport.U.park(false, nanos);
            LockSupport.setBlocker(t, null);
        }
    }

狀態查詢操作,基於佇列的狀態查詢是不精確的

    /**
     * 當前可重入互斥鎖是不是公平鎖
     */
    public final boolean isFair() {
        return sync instanceof FairSync;
    }

    /**
     * 鎖是不是被當前執行緒持有
     */
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    /**
     * 鎖是不是已經被佔用,同步狀態不為 0
     */
    public boolean isLocked() {
        return sync.isLocked();
    }

    /**
     * 當前執行緒持有同步狀態的計數值
     */
    public int getHoldCount() {
        return sync.getHoldCount();
    }