【AQS】核心实现

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

文章首发于:clawhub.club


AQS(AbstractQueuedSynchronizer)是Java并发工具的基础,采用乐观锁,通过CAS与自旋轻量级的获取锁。
下面简单分析一下他的核心实现:

核心属性

锁相关属性:

     /**
         * The synchronization state.
         * 同步状态,0代表锁没有被占用,大于0代表锁被占用且表示锁被重入的次数
         */
        private volatile int state;
        /**
        *存储当前获取锁的线程,继承自AbstractOwnableSynchronizer
        */
        private transient Thread exclusiveOwnerThread;

同步队列相关属性:

        /**
         * 对首,只是一个标志位,不存储线程
         */
        private transient volatile Node head;

        /**
         * 队尾,新增加的等待线程入队节点
         */
        private transient volatile Node tail;

Node节点中重要属性:

        /**
        *当前节点所代表的线程
        */
        volatile Thread thread;

        // 双向链表,每个节点需要保存自己的前驱节点和后继节点的引用
        volatile Node prev;
        volatile Node next;

        // 线程所处的等待锁的状态,初始化时,该值为0
        volatile int waitStatus;
        static final int CANCELLED =  1;
        static final int SIGNAL    = -1;
        static final int CONDITION = -2;
        static final int PROPAGATE = -3;

        /**
        * 用于条件队列与共享锁
        */
        Node nextWaiter;

状态

AQS中的状态,代表锁是否被获取,如果为0,则没有被任何线程获取,如果是独占锁的话,值为1,如果是共享锁,则值为持有锁的线程的数量。
当讨论独占锁时,除了获取锁之外,还要记录一下获取到锁的线程,所以有了类AbstractOwnableSynchronizer中的exclusiveOwnerThread属性。

队列

AQS中的队列是双向链表,依赖于Node节点中的prev和next属性,队列中存储了等待获取锁的集合。队列中有head和tail节点,头节点不存储等待锁线程。
如图:

2019102910018\_1.png

同步队列.png

CAS

以前也好好看过CAS操作,主要依赖于Unsafe类中的各种方法,保证只有一个线程能修改值,如果失败则通过for循环不断重试,直到修改成功,入等待节点入队列的操作。

        /**
         * Inserts node into queue, initializing if necessary. See picture above.
         * @param node the node to insert
         * @return node's predecessor
         */
        private Node enq(final Node node) {
            for (;;) {
                Node t = tail;
                if (t == null) { // Must initialize
                    if (compareAndSetHead(new Node()))
                        tail = head;
                } else {
                    node.prev = t;
                    if (compareAndSetTail(t, node)) {
                        t.next = node;
                        return t;
                    }
                }
            }
        }

参考:
https://segmentfault.com/a/1190000016058789


来源:https://www.jianshu.com/p/347ea7f881f8

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 【AQS】核心实现

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏