AQS源码浅析(2)——属性及结构

2022-04-02  本文已影响0人  墨_0b54

数据结构

AQS内部是一个双向链表,其中head是一个虚节点。

//      +------+  prev +-----+       +-----+
// head |      | <---- |     | <---- |     |  tail
//      +------+       +-----+       +-----+
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; //处于条件队列
        static final int PROPAGATE = -3; //共享模式才会使用的,无条件传播acquireShared

        //node状态,上面的几个状态值和0,同步队列中初始化为 0,条件队列中初始化为 CONDITION。
        //使用 CAS 进行修改,大于0意味着节点不需要唤醒。
        volatile int waitStatus;

        //链接到当前节点线程的前驱节点(依赖前驱节点的waitStatus进行后续操作)。
        //在取消前驱时,找到未取消的前驱并链接,因为【head永远不会被取消】。
        //只有在成功得到锁后才成为head。被取消的线程永远不会得到锁,且线程只会取消自己所属节点。
        volatile Node prev; 

        //链接到当前节点线程解除阻塞被释放后的后继节点。
        //在入队期间分配,在绕过取消的前驱时进行调整,并在出队时清空为null(为了 GC)。
        //enq 操作直到prev分配后才分配前驱的next字段,因此next为null并不意味着该节点位于队列末尾。
        //如果next字段为null,我们可以从尾部扫描 prev 进行双重检查。CANCELLED节点的next字段设置为指向节点本身。
        volatile Node next;
           
        volatile Thread thread; //使该节点入队的线程。使用后为null

        //独占模式时,如果在条件队列(只有在独占模式下才能访问)是一个单向链表,nextWaiter是单向链表的next指针。
        //非独占模式时,指向SHARED代表共享,指向EXCLUSIVE代表独占
        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
        }//用于建立初始头部或SHARED标记

        Node(Thread thread, Node mode) {     // 给addWaiter方法使用
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // 给Condition对象使用
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

//条件队列Condition数据结构
public class ConditionObject implements Condition, java.io.Serializable {
        /** First node of condition queue. */
        private transient Node firstWaiter;
        /** Last node of condition queue. */
        private transient Node lastWaiter;
}

Node注释翻译

条件队列相关

AQS属性

//等待队列的头指针,延迟初始化。除初始化外,只能通过 setHead 方法进行修改。
//注意:如果head存在,它的waitStatus一定不是CANCELLED。
private transient volatile Node head;

//等待队列的尾部指针,延迟初始化。仅通过方法 enq 修改以添加新的等待节点。
private transient volatile Node tail;

//同步器状态值
private volatile int state;

AQS架构图

image.png

来源:从ReentrantLock的实现看AQS的原理及应用 - 美团技术团队 (meituan.com)

上一篇 下一篇

猜你喜欢

热点阅读