• 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();
        }
    
  • 相关阅读:
    JSON.parse()和JSON.stringify()
    php结合layui实现前台加后台操作
    微信拨打电话功能
    视觉差效果
    前端开发面试题
    字符串分割--java中String.split()用法
    vue.js实现购物车功能
    localStorage使用总结
    canvas 实现赛车小游戏
    canvas 实现飞碟射击游戏
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10049383.html
Copyright © 2020-2023  润新知