jdk1.8源码分析之AbstractQueuedLongSynchronizer

AbstractQueuedLongSynchronizer 即AQS。 通过一个FIFO的双向队列实现的一个同步器。

  • 通过源码了解AQS提供的方法,可以进一步加深对锁实现的理解。AQS是可重入锁,可重入读写锁的一个基础支撑,提供了一系列的方法。
  • //
    * <pre>
    *      +------+  prev +-----+       +-----+
    * head |      | <---- |     | <---- |     |  tail
    *      +------+       +-----+       +-----+
    * </pre>
    public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer
        implements java.io.Serializable {
    
        private static final long serialVersionUID = 7373984972572414691L;
    
        /**
         * Creates a new {@code AbstractQueuedSynchronizer} instance
         * with initial synchronization state of zero.
         */
        protected AbstractQueuedSynchronizer() { }
        // 队列 头结点  volatile  修饰保证了可见性  transient  保证了序列化时不序列化该字段
        private transient volatile Node head;
        // 对列 尾结点
        private transient volatile Node tail;
        //  同步状态 
        private volatile int state;
        // 为cas 操作提供支持   unsafe 负责CAS 操作
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final long stateOffset;
        private static final long headOffset;
        private static final long tailOffset;
        private static final long waitStatusOffset;
        private static final long nextOffset;
        
        // 内部静态节点类 
        static final class Node {
            /** Marker to indicate a node is waiting in shared mode
            * 标记该节点时需要获取的是共享模式锁
             */
            static final Node SHARED = new Node();
            
            /** Marker to indicate a node is waiting in exclusive mode
            **  标记该节点是等待获取独占模式锁
             */
            static final Node EXCLUSIVE = null;
            /** waitStatus value to indicate thread has cancelled */
            // 取消状态  当线程取消尝试获取锁,等待状态置为取消。 
            // 节点处于该状态,则当前节点会被跳过。
            static final int CANCELLED =  1;
            /** waitStatus value to indicate successor's thread needs unparking
            * waitStatus值,指示后续线程需要释放
             */
            static final int SIGNAL    = -1;
            
            /** waitStatus value to indicate thread is waiting on condition
            * 指示线程正在等待条件
              */
            static final int CONDITION = -2;
            /**
             * waitStatus value to indicate the next acquireShared should
             * unconditionally propagate
             * 指示下一个acquireShared应该*无条件传播  
             */
            static final int PROPAGATE = -3;
            // 等待状态
            volatile int waitStatus;
            // 前一个节点
            volatile Node prev;
            // 下一个节点
            volatile Node next;
            // 当前节点持有的线程
            volatile Thread thread;
            // 下一个等待者
            Node nextWaiter;
            // 判断下一个等待者是否是共享模式节点
            final boolean isShared() {
                return nextWaiter == SHARED;
            }
            //获取当前节点的前一个节点
            final Node predecessor() throws NullPointerException {
                Node p = prev;
                if (p == null)
                    throw new NullPointerException();
                else
                    return p;
            }
            // 构造函数,仅用于创建头结点和共享模式标记
            // 这里可以看出初始化头结点是一个空节点。
            Node() {    // Used to establish initial head or SHARED marker
            }
            // 构造函数,用于创建等待者节点
            Node(Thread thread, Node mode) {     // Used by addWaiter
                this.nextWaiter = mode;
                this.thread = thread;
            }
            // 构造函数,绑定线程和等待状态来创建节点
            Node(Thread thread, int waitStatus) { // Used by Condition
                this.waitStatus = waitStatus;
                this.thread = thread;
            }
        }
        
        // AQS类 方法
        
        // 通过使用unsafed CAS 来设置state的值
        protected final boolean compareAndSetState(int expect, int update) {
            // See below for intrinsics setup to support this
            return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
        }
        
        // 插入节点,如果节点没有初始化,则先初始化头结点。
        // 初始化完成 ,则将使用尾插法插入node节点,返回node节点的头结点。
        // 如果第一次调用,则返回的就是头结点。
        private Node enq(final Node node) {
            for (;;) {
                Node t = tail;
                if (t == null) { // Must initialize
                 // CAS 设置头结点
                    if (compareAndSetHead(new Node()))
                        tail = head;
                } else {
                    // node 上一个节点设置为当前的尾结点
                    node.prev = t;
                    // CAS设置node为尾结点
                    if (compareAndSetTail(t, node)) {
                        // node设置为尾结点成功,则设置之前尾结点的下一个节点时node节点。
                        //这样就构成了一个双向的链表
                        t.next = node;
                        return t;
                    }
                }
            }
        }
        
        // 添加等待节点
        // mode  锁模式,独占和共享
        private Node addWaiter(Node mode) {
            //构造一个持有当前线程,指定模式的节点
            Node node = new Node(Thread.currentThread(), mode);
            // Try the fast path of enq; backup to full enq on failure
            Node pred = tail;
            //尾结点不为空,则尾插法插入node节点。
            //尾结点不为空,说明该队列已经初始化完成
            if (pred != null) {
                node.prev = pred;
                if (compareAndSetTail(pred, node)) {
                    pred.next = node;
                    return node;
                }
            }
            // 尾结点为空,则初始化对列,尾插法插入node节点
            enq(node);
            //返回 持有当前线程的节点,也是双向队列的尾结点
            return node;
        }
        
        //设置头结点  node节点设置为头结点 ,头结点持有的线程置为null
        // 前向指针指向null
        private void setHead(Node node) {
            head = node;
            node.thread = null;
            node.prev = null;
        }
        
        // 尝试唤醒继任节点
        private void unparkSuccessor(Node node) {
            /*
             * If status is negative (i.e., possibly needing signal) try
             * to clear in anticipation of signalling.  It is OK if this
             * fails or if status is changed by waiting thread.
             */
            int ws = node.waitStatus;
            // node 节点的等待状态小于0,则设置其等待状态为0
            // 0 代表是等待状态之外的其他状态
            if (ws < 0)
                compareAndSetWaitStatus(node, 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;
            // 没有下一个节点或者下一个节点持有的线程已被取消
            if (s == null || s.waitStatus > 0) {
                s = null;
                //从后向前循环查找等待状态小于等于0的节点赋值给s,至到node节点终止
                // 从后往前找到node节点第一个未被取消的继任者 
                // 为何这里不从node节点开始,从前往后查找???? 因为新节点采用尾插法插入,所以从后向前找,避免产生不可预料行为
                for (Node t = tail; t != null && t != node; t = t.prev)
                    if (t.waitStatus <= 0)
                        s = t;
            //找到则唤醒节点的线程
            if (s != null)
                LockSupport.unpark(s.thread);
        }
        
          // 共享模式锁的释放
          private void doReleaseShared() {
            /*
             * Ensure that a release propagates, even if there are other
             * in-progress acquires/releases.  This proceeds in the usual
             * way of trying to unparkSuccessor of head if it needs
             * signal. But if it does not, status is set to PROPAGATE to
             * ensure that upon release, propagation continues.
             * Additionally, we must loop in case a new node is added
             * while we are doing this. Also, unlike other uses of
             * unparkSuccessor, we need to know if CAS to reset status
             * fails, if so rechecking.
             */
            for (;;) {
                Node h = head;
                // 头节点不为空,且头节点不等于尾节点
                if (h != null && h != tail) {
                    int ws = h.waitStatus;
                    //  表示后继者需要释放
                    if (ws == Node.SIGNAL) {
                        //设置节点等待状态为0 
                        if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                            continue;            // loop to recheck cases
                            // 设置成功,则唤醒后继者
                        unparkSuccessor(h);
                    }
                    // 等待状态为0,设置等待状态为-3失败则返回开始处继续循环
                    else if (ws == 0 &&!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                        continue;                // loop on failed CAS
                }
                //等于头结点结束循环
                if (h == head)                   // loop if head changed
                    break;
            }
        }  
        
        private void setHeadAndPropagate(Node node, int propagate) {
            Node h = head; // Record old head for check below
            //设置头结点
            setHead(node);
            /*
             * Try to signal next queued node if:
             *   Propagation was indicated by caller,
             *     or was recorded (as h.waitStatus either before
             *     or after setHead) by a previous operation
             *     (note: this uses sign-check of waitStatus because
             *      PROPAGATE status may transition to SIGNAL.)
             * and
             *   The next node is waiting in shared mode,
             *     or we don't know, because it appears null
             *
             * The conservatism in both of these checks may cause
             * unnecessary wake-ups, but only when there are multiple
             * racing acquires/releases, so most need signals now or soon
             * anyway.
             */
             // 原来的头结点为空,或者其等待状态小于0   或
             // 现在的头结点为空 或者等待状态小于0 
            if (propagate > 0 || h == null || h.waitStatus < 0 ||
                (h = head) == null || h.waitStatus < 0) {
                Node s = node.next;
                //下一个节点为空或者是共享模式的则尝试释放共享锁
                if (s == null || s.isShared())
                    doReleaseShared();
            }
        }
        
        
        // 设置node节点为取消状态,则该节点不再去获取锁
        private void cancelAcquire(Node node) {
            // Ignore if node doesn't exist
            if (node == null)
                return;
            // 节点绑定线程置为空
            node.thread = null;
        
            // Skip cancelled predecessors
            Node pred = node.prev;
            // 跳过已经取消的节点
            while (pred.waitStatus > 0)
              // 设置node的前一个节点为pred的前一个节点
                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.
            // pred的下一个节点
            Node predNext = pred.next;
        
            // Can use unconditional write instead of CAS here.
            // After this atomic step, other Nodes can skip past us.
            // Before, we are free of interference from other threads.
            // 节点状态设置为已取消
            node.waitStatus = Node.CANCELLED;
        
            // If we are the tail, remove ourselves.
            // node 节点时尾结点,设置pred上一个节点为尾节点
            if (node == tail && compareAndSetTail(node, pred)) {
                // 设置pred的下一个节点为null
                compareAndSetNext(pred, predNext, null);
            } else {
                // If successor needs signal, try to set pred's next-link
                // so it will get one. Otherwise wake it up to propagate.
                int ws;
                // 
                if (pred != head &&
                    ((ws = pred.waitStatus) == Node.SIGNAL ||
                     (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                    pred.thread != null) {
                    Node next = node.next;
                    if (next != null && next.waitStatus <= 0)
                        compareAndSetNext(pred, predNext, next);
                } else {
                    unparkSuccessor(node);
                }
                // node下一个节点指向自己,则此时没有节点指向node,node不可达即可被回收
                // 为何不直接置为null
                node.next = node; // help GC
            }
        }
        //尝试获取失败后 
        private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
            int ws = pred.waitStatus;
            // 线程应该被阻塞
            if (ws == Node.SIGNAL)
                /*
                 * This node has already set status asking a release
                 * to signal it, so it can safely park.
                 */
                return true;
            if (ws > 0) {
                /*
                 * Predecessor was cancelled. Skip over predecessors and
                 * indicate retry.
                 */
                 //从pred开始循环向前找到一个未被取消的节点
                do {
                    node.prev = pred = pred.prev;
                } while (pred.waitStatus > 0);
                //找到的pred 的下一个节点置为node。
                pred.next = node;
            } else {
                /*
                 * waitStatus must be 0 or PROPAGATE.  Indicate that we
                 * need a signal, but don't park yet.  Caller will need to
                 * retry to make sure it cannot acquire before parking.
                 */
                 //等待状态为0或者 PROPAGATE,则CAS尝试将状态设置为 SIGNAL
                 // 
                compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
            }
            return false;
        }
        
        /**
         * Convenience method to interrupt current thread.
         */
        static void selfInterrupt() {
            // 线程中断
            Thread.currentThread().interrupt();
        }
        
        // 优雅的挂起线程的方法,返回线程是否中断成功
        private final boolean parkAndCheckInterrupt() {
            // 挂起线程 
            LockSupport.park(this);
            return Thread.interrupted();
        }
        
       
        /**
         * Acquires in exclusive uninterruptible mode for thread already in
         * queue. Used by condition wait methods as well as acquire.
         *
         * @param node the node
         * @param arg the acquire argument
         * @return {@code true} if interrupted while waiting
         */
          // 独占模式获取在队列里的线程,用于wait 或者acquire 方法
        final boolean acquireQueued(final Node node, int arg) {
            boolean failed = true;
            try {
                boolean interrupted = false;
                for (;;) {
                    final Node p = node.predecessor();
                    //node 节点的前一个节点为头节点  尝试获取锁成功
                    if (p == head && tryAcquire(arg)) {
                        // 当前节点的线程获取锁成功,头节点设置为 node
                        setHead(node);
                        //原来的头节点next指向null
                        p.next = null; // help GC
                        failed = false;
                        // 返回false
                        return interrupted;
                    }
                    // 获取失败后是否应该挂起 且 尝试挂起 返回是否中断成功
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        interrupted = true;
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
        //尝试获取独占模式对象,留给子类实现
        protected boolean tryAcquire(int arg) {
            throw new UnsupportedOperationException();
        }
        
        //获取锁
        public final void acquire(int arg) {
            if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                //尝试获取锁失败,中断当前线程
                selfInterrupt();
        }
        
        //非中断模式获取锁
        //
        private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
            // 当前线程以独占模式加入等待队列,返回持有当前线程的节点
            final Node node = addWaiter(Node.EXCLUSIVE);
            boolean failed = true;
            try {
                for (;;) {
                    final Node p = node.predecessor();
                    if (p == head && tryAcquire(arg)) {
                        setHead(node);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                    // 如果node节点持有的当前线程应该被挂起且已经被中断则抛出中断异常
                    // 中断异常 ,那么实现了非中断模式获取锁,如果使用此方法,
                    // 那么 获取锁的线程不能被中断
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        throw new InterruptedException();
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
        
        // 带有超时时间获取锁,一旦超时则返回获取失败
        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);
            boolean failed = true;
            try {
                for (;;) {
                    final Node p = node.predecessor();
                    if (p == head && tryAcquire(arg)) {
                        setHead(node);
                        p.next = null; // help GC
                        failed = false;
                        return true;
                    }
                    nanosTimeout = deadline - System.nanoTime();
                    if (nanosTimeout <= 0L)
                        return false;
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        nanosTimeout > spinForTimeoutThreshold)
                        LockSupport.parkNanos(this, nanosTimeout);
                    if (Thread.interrupted())
                        throw new InterruptedException();
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
        
        //共享模式尝试获取锁
        private void doAcquireShared(int arg) {
            // 共享模式加入等待队列
            final Node node = addWaiter(Node.SHARED);
            boolean failed = true;
            try {
                boolean interrupted = false;
                for (;;) {
                    final Node p = node.predecessor();
                    //node 的前一个节点等于头节点
                    if (p == head) {
                        // 尝试获取共享锁
                        int r = tryAcquireShared(arg);
                        if (r >= 0) {
                            //设置头节点及其等待状态
                            setHeadAndPropagate(node, r);
                            p.next = null; // help GC
                            if (interrupted)// 调用中断方法
                                selfInterrupt();
                            failed = false;
                            return;
                        }
                    }
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        interrupted = true;
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
        
        //锁释放 子类实现
        protected boolean tryRelease(int arg) {
            throw new UnsupportedOperationException();
        }
        
        // 尝试获取共享锁
        protected int tryAcquireShared(int arg) {
            throw new UnsupportedOperationException();
        }
        
        //尝试获取锁 
        public final void acquire(int arg) {
            if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                //获取失败,线程中断
                selfInterrupt();
        }
        
        // 释放锁
        public final boolean release(int arg) {
            // 尝试释放锁 
            if (tryRelease(arg)) {
                Node h = head;
                //头节点不为空,且头节点等待状态不等于0 唤醒下一个等待者
                if (h != null && h.waitStatus != 0)
                    unparkSuccessor(h);
                return true;
            }
            return false;
        }
        
        // 尝试获取共享锁  
        public final void acquireShared(int arg) {
            if (tryAcquireShared(arg) < 0)
                doAcquireShared(arg);
        }
        
        // 释放共享锁
        public final boolean releaseShared(int arg) {
            if (tryReleaseShared(arg)) {
                doReleaseShared();
                return true;
            }
            return false;
        }
        
        // 是否还有排队的线程
        public final boolean hasQueuedThreads() {
            return head != tail;
        }
        
        // 是否有线程获取过同步器
        public final boolean hasContended() {
            return head != null;
        }
        
        //返回等待最久的线程  
        public final Thread getFirstQueuedThread() {
            // handle only fast path, else relay
            return (head == tail) ? null : fullGetFirstQueuedThread();
        }
        
        // 查找最靠近头节点的节点持有的线程
        private Thread fullGetFirstQueuedThread() {
            /*
             * The first node is normally head.next. Try to get its
             * thread field, ensuring consistent reads: If thread
             * field is nulled out or s.prev is no longer head, then
             * some other thread(s) concurrently performed setHead in
             * between some of our reads. We try this twice before
             * resorting to traversal.
             */
            Node h, s;
            Thread st;
            // 尝试获取头节点的下一个节点的线程
            if (((h = head) != null && (s = h.next) != null &&
                 s.prev == head && (st = s.thread) != null) ||
                ((h = head) != null && (s = h.next) != null &&
                 s.prev == head && (st = s.thread) != null))
                return st;
        
            /*
             * Head's next field might not have been set yet, or may have
             * been unset after setHead. So we must check to see if tail
             * is actually first node. If not, we continue on, safely
             * traversing from tail back to head to find first,
             * guaranteeing termination.
             */
        
            Node t = tail;
            Thread firstThread = null;
            // 从后向前循环查找节点持有的线程
            // 不是从前往后查找的原因在于有可能其他线程在设置头节点,
            // 一种情况当前线程获取的头节点时原来的头节点,当获取头节点的下一个节点时
            // 此时有另一个线程已经将原来头节点的next指向null,那么将会导致此次查找失败。
            //这也是双向链表的一个好处。头节点在设置,从尾节点查找,避免产生冲突。
            while (t != null && t != head) {
                Thread tt = t.thread;
                if (tt != null)
                    firstThread = tt;
                t = t.prev;
            }
            return firstThread;
        }
        
        //返回给定线程是否正在排队
        public final boolean isQueued(Thread thread) {
            if (thread == null)
                throw new NullPointerException();
            for (Node p = tail; p != null; p = p.prev)
                if (p.thread == thread)
                    return true;
            return false;
        }
        
        //是否有一个排他模式的线程在等待获取锁
        final boolean apparentlyFirstQueuedIsExclusive() {
            Node h, s;
            return (h = head) != null &&
                (s = h.next)  != null &&
                !s.isShared()         &&
                s.thread != null;
        }
        
        // 是否有其他线程等待时间比当前线程更久
        // 用来实现公平锁
        public final boolean hasQueuedPredecessors() {
            // The correctness of this depends on head being initialized
            // before tail and on head.next being accurate if the current
            // thread is first in queue.
            Node t = tail; // Read fields in reverse initialization order
            Node h = head;
            Node s;
            return h != t &&
                ((s = h.next) == null || s.thread != Thread.currentThread());
        }
        
        // 返回对列长度
        public final int getQueueLength() {
            int n = 0;
            for (Node p = tail; p != null; p = p.prev) {
                if (p.thread != null)
                    ++n;
            }
            return n;
        }
        
        //返回队列持有的线程集合
        public final Collection<Thread> getQueuedThreads() {
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node p = tail; p != null; p = p.prev) {
                Thread t = p.thread;
                if (t != null)
                    list.add(t);
            }
            return list;
        }
        
        
        //返回排他模式的线程集合
        public final Collection<Thread> getExclusiveQueuedThreads() {
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node p = tail; p != null; p = p.prev) {
                if (!p.isShared()) {
                    Thread t = p.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
        
        // 获取共享模式的线程集合
        public final Collection<Thread> getSharedQueuedThreads() {
            ArrayList<Thread> list = new ArrayList<Thread>();
            for (Node p = tail; p != null; p = p.prev) {
                if (p.isShared()) {
                    Thread t = p.thread;
                    if (t != null)
                        list.add(t);
                }
            }
            return list;
        }
        
        }
    
    

     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值