Java8 ConcurrentLinkedDeque 源码解析

 目录

1、定义

3、add / offer / addAll

4、peek / poll / remove

5、unlinkFirst / unlinkLast

6、unlink 

7、iterator / descendingIterator


      ConcurrentLinkedDeque表示一个无固定容量的,线程安全的,基于CAS而非ReentrantLock互斥锁实现的双端队列,其实现方式跟ConcurrentLinkedQueue类似,本篇博客就详细探讨该类的实现细节。

1、定义

     ConcurrentLinkedDeque的类继承关系如下:

只实现了Deque接口,未实现BlockingDeque接口,相关方法的功能可以参考《Java8 LinkedBlockingDeque 源码解析》

该类包含的实例属性如下:

//链表头
private transient volatile Node<E> head;

//链表尾
private transient volatile Node<E> tail;

private static final int HOPS = 2;

  包含的静态属性通过static代码块初始化,如下:

其中PREV_TERMINATOR和NEXT_TERMINATOR都是两个静态常量,Node是一个静态的内部类,实现如下:

static final class Node<E> {
        volatile Node<E> prev; //前一个节点
        volatile E item; //关联的元素
        volatile Node<E> next; //下一个节点

        Node() {  // default constructor for NEXT_TERMINATOR, PREV_TERMINATOR
        }

        Node(E item) {
            UNSAFE.putObject(this, itemOffset, item);
        }
        
        //compareAndSwapObject和putOrderedObject都会保证修改对其CPU立即可见
        boolean casItem(E cmp, E val) {
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
        }

        void lazySetNext(Node<E> val) {
            UNSAFE.putOrderedObject(this, nextOffset, val);
        }

        boolean casNext(Node<E> cmp, Node<E> val) {
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
        }

        void lazySetPrev(Node<E> val) {
            UNSAFE.putOrderedObject(this, prevOffset, val);
        }

        boolean casPrev(Node<E> cmp, Node<E> val) {
            return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
        }


        private static final sun.misc.Unsafe UNSAFE;
        private static final long prevOffset;
        private static final long itemOffset;
        private static final long nextOffset;
        
        //获取三个属性的偏移量
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> k = Node.class;
                prevOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("prev"));
                itemOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("item"));
                nextOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("next"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }

 2、构造方法

public ConcurrentLinkedDeque() {
         //初始化head和tail属性
        head = tail = new Node<E>(null);
    }

public ConcurrentLinkedDeque(Collection<? extends E> c) {
        // Copy c into a private chain of Nodes
        Node<E> h = null, t = null;
        //遍历集合c
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<E>(e);
            if (h == null)
                h = t = newNode; //链表未初始化
            else {
                //插入到tail的后面
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        initHeadTail(h, t);
    }

private void initHeadTail(Node<E> h, Node<E> t) {
        if (h == t) {
            if (h == null) //两个都是空
                h = t = new Node<E>(null);
            else {
                //两个非空,即此时链表中只有一个元素,构建一个空节点作为tail
                Node<E> newNode = new Node<E>(null);
                t.lazySetNext(newNode);
                newNode.lazySetPrev(t);
                t = newNode;
            }
        }
        head = h;
        tail = t;
    }

3、add / offer / addAll

     add和offer类方法的核心就是linkFirst和linkLast方法。 

public boolean add(E e) {
        return offerLast(e);
    }

public void addFirst(E e) {
        linkFirst(e);
    }

public void addLast(E e) {
        linkLast(e);
    }

public boolean offer(E e) {
        return offerLast(e);
    }

public boolean offerFirst(E e) {
        linkFirst(e);
        return true;
    }

public boolean offerLast(E e) {
        linkLast(e);
        return true;
    }


private void linkFirst(E e) {
        checkNotNull(e);
        final Node<E> newNode = new Node<E>(e);

        restartFromHead:
        for (;;)
            for (Node<E> h = head, p = h, q;;) {
                if ((q = p.prev) != null &&     //head前面两个节点都非空
                    (q = (p = q).prev) != null)
                    //如果head节点发生变更,p等于新的head节点,否则p等于q,然后开始下一次for循环,直到有一个节点的prev为null,即找到链表最前面的一个节点
                    p = (h != (h = head)) ? h : q;
                else if (p.next == p) // 这个节点原来是head,即将被移除,重新读取head
                    continue restartFromHead;
                else {
                    //第一个的if条件不成立,p的prev为null,p就是链表中第一个节点
                    newNode.lazySetNext(p); // CAS piggyback
                    if (p.casPrev(null, newNode)) { 
                        //如果cas修改prev成功
                        if (p != h) //如果p不等于head则修改head,当p等于head的前一个节点时p就不等于head
                                    //如果等于则不修改,下一次调用此方法时再修改,相当于节省了一次casHead调用
                            //cas修改head,如果修改失败,则表示其他线程修改了head,其他线程插入节点只能插入到nowNode的后面,所以只要有一个线程修改成功即可        
                            casHead(h, newNode);  
                        return;
                    }
             
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值