AbstractQueuedSynchronizer--基于CAS自旋volatile变量插入尾节点

Posted ljjnbpy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AbstractQueuedSynchronizer--基于CAS自旋volatile变量插入尾节点相关的知识,希望对你有一定的参考价值。

    private transient volatile Node tail;
    
      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;
                    }
                }
            }
        }

上述代码是AbstractQueuedSynchronizer中关于如何往Node中添加尾节点的代码,使用的CAS自旋volatile变量法,解决高并发下插入尾节点不同步问题。

1.假如尾节点为空,说明节点队列为空,初始化一个头结点指向尾节点的队列;

2.继续for循环,这次进入else中,先把插入节点的前置指向尾节点(这个尾节点不一定是真的尾节点,有可能在此期间被其他线程改变了,所以有下面的),然后进行cas操作,假如t是此时真实的尾节点,就将node改为尾节点,并将t.next指向node,然后返回。

如果compareAndSetTail(t, node)为false,说明这个尾节点不是真的尾节点,在此期间被其他线程改变了,故继续自旋 ,Node t = tail 会一直将自认为的尾节点赋给t,直至compareAndSetTail成功。

 

 

    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;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

 

 

 

上述addWaiter方法提供了一种快捷一点的插入节点方法,将空队列和自旋的判断放在enq(node)中,提升了速度,设计的很精巧

以上是关于AbstractQueuedSynchronizer--基于CAS自旋volatile变量插入尾节点的主要内容,如果未能解决你的问题,请参考以下文章

ReentrantLock原理源码详解

一行一行源码分析清楚 AbstractQueuedSynchronizer

Java并发-- AQS 原理