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();
    }

猜你喜欢

转载自www.cnblogs.com/zhuxudong/p/10049383.html