• 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)中,提升了速度,设计的很精巧

  • 相关阅读:
    element-ui做表单验证 v-for遍历表单 自动生成校验规则 pc移动双适配
    element-ui练习使用总结
    js监听页面标签切换
    对象数组,按照没想中特定的属性(按中文拼音)排序
    调用七牛云存储文件,返回url
    javascript中的class类 以及class的继承
    javascript原型继承
    javascript面向对象 用new创建一个基于原型的javascript对象
    java中的变量和数据类型
    css的伪元素
  • 原文地址:https://www.cnblogs.com/ljjnbpy/p/10029797.html
Copyright © 2020-2023  润新知