Java8 ConcurrentLinkedQueue和LinkedTransferQueue 源码解析

  目录

一、ConcurrentLinkedQueue

1、定义

2、构造方法

 3、add / offer / addAll

4、 peek / poll / remove

5、iterator / Itr

二、LinkedTransferQueue

 1、定义

2、add / offer / put

3、take / poll /peek

4、remove / drainTo

5、transfer / tryTransfer / getWaitingConsumerCount

6、xfer

7、iterator / Itr


      ConcurrentLinkedQueue表示一个无固定容量的,线程安全的,先进先出的队列,跟LinkedBlockingQueue不同的是,该类没有使用ReentrantLock互斥锁来实现线程安全,而是通过CAS来保证的,另外,该类没有实现BlockingQueue接口。LinkedTransferQueue也是表示一个无固定容量的,线程安全的,先进先出的队列,同样没有使用ReentrantLock互斥锁,而是采用跟SynchronousQueue中的用于实现FIFO模式的内部类TransferQueue类似的机制实现。

一、ConcurrentLinkedQueue

1、定义

      ConcurrentLinkedQueue的类继承关系如下:

没有实现BlockingQueue接口,只实现了Queue接口,因为BlockingQueue接口继承自Queue接口,所以Queue接口方法的描述也可以参考《Java8 ArrayBlockingQueue 源码解析》。该类包含的实例属性如下:

//链表头节点
private transient volatile Node<E> head;
//链表尾节点
private transient volatile Node<E> tail;

 包含的静态属性如下,通过Unsafe类获取head和tail属性的偏移量:

其中Node是一个静态的私有内部类,定义如下:

private static class Node<E> {
        volatile E item;
        volatile Node<E> next;
        
        //创建一个新的Node节点
        Node(E item) {
            //putObject和putOrderedObject底层会通过内存屏障指令保证修改对其他CPU立即可见
            UNSAFE.putObject(this, itemOffset, item);
        }

        //修改item属性
        boolean casItem(E cmp, E val) {
            //底层cas动作会通过lock指令前缀保证修改对其他CPU立即可见
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
        }
        
        //修改next属性
        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);
        }

        //获取属性的偏移量
        private static final sun.misc.Unsafe UNSAFE;
        private static final long itemOffset;
        private static final long nextOffset;

        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> k = Node.class;
                itemOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("item"));
                nextOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("next"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }

2、构造方法

      构造方法会初始化head和tail属性,保证其非空

public ConcurrentLinkedQueue() {
        head = tail = new Node<E>(null);
    }

public ConcurrentLinkedQueue(Collection<? extends E> c) {
        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 {
                //插入到链表末尾
                t.lazySetNext(newNode);
                t = newNode;
            }
        }
        if (h == null)
           //如果集合c是空的
            h = t = new Node<E>(null);
        head = h;
        tail = t;
    }

 3、add / offer / addAll

      理解下列代码逻辑需要知道tail节点并不一定是链表中最后一个节点,为了提升性能,这些方法并不会立即修改tail,而是等下一次调用时判断tail节点后面还有下一个节点时才会尝试更新tail节点。 

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

public boolean offer(E e) {
        checkNotNull(e);
        //创建新节点
        final Node<E> newNode = new Node<E>(e);

        for (Node<E> t = tail, p = t;;) {
            Node<E> q = p.next;
            if (q == null) {
                //p是最后一个节点
                if (p.casNext(null, newNode)) {
                    //将新节点作为p的next节点
                    if (p != t) 
                       //初始状态下p和t是一致的,但是如果一开始q不为null,即有其他线程并行的执行offer方法导致进入了else分支,则p
                       //被置为q,p和t就不同了,此时t是当前的tail节点,这时需要将newNode修改为新的tail节点,如果修改失败了,则下一次调用
                       //offer方法,q不为null,会再次尝试修改
                       //如果一开始q为null,则tail不变,直接返回true,下一次再调用offer方法q就不等于null了
                        casTail(t, newNode);  // Failure is OK.
                    return true;
                }
                //cas修改失败,有其他线程也在修改p的next属性,下一次for循环进入else分支
            }
            else if (p == q) //p等于q说明p原来是head节点,从链表中移除了,这时会有新的head节点
                //如果t还是tail节点说明p已经从链表中移除,p等于t,如果tail变了说明tail也可能被移除了,从head开始重新遍历
                p = (t != (t = tail)) ? t : head;
            else
                //初始状态下p等于t的,因为q不为null进入else分支后p就等于q了,即将新节点插入到q的后面
                //再下一次p就不等于t了,如果此时tail节点还变了,将p置为t,将新节点插入到t的后面
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

public boolean addAll(Collection<? extends E> c) {
        if (c == this) //参数校验
            throw new IllegalArgumentException();

        //遍历集合c,将c中的元素构成一个链表,beginningOfTheEnd为该链表的链表头
        Node<E> beginningOfTheEnd = null, last = null;
        for (E e : c) {
            checkNotNull(e);
            Node<E> newNode = new Node<E>(e);
            if (beginningOfTheEnd == null)
                //初始化链表
                beginningOfTheEnd = last = newNode;
            else {
                //插入到链表末尾
                last.lazySetNext(newNode);
                last = newNode;
            }
        }
        //集合c为空
        if (beginningOfTheEnd == null)
            return false;

        //将beginningOfTheEnd当做一个普通的新节点插入到现有链表中,逻辑同offer方法
        for (Node<E> t = tail, p = t;;) {
            Node<E> q = p.next;
            if (q == null) {
                //p是最后一个节点
                if (p.casNext(null, beginningOfTheEnd)) {
                    //上一步cas修改成功后,此时tail没有变,再插入新的节点就会发现q不为null了,会一直往后遍历找到last
                    //往last后面插入新的节点
                    if (!casTail(t, last)) {
                        //如果tail修改失败,即有其他线程在并行的修改tail,此时last的next属性不为空
                        t = tail;
                        if (last.next == null)
                            casTail(t, last); //再一次尝试修改
                    }
                    //将tail修改成last成功
                    return true;
                }
                // Lost CAS race to another thread; re-read next
            }
            else if (p == q)
                p = (t != (t = tail)) ? t : head;
            else
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

private boolean casTail(Node<E> cmp, Node<E> val) {
        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
    }

4、 peek / poll / remove

      同添加元素的方法,移除元素时不会立即将该元素对应的节点移除,不会更新head节点,即从head节点开始,可能有多个节点的item属性是null的情形,然后在某些条件下,比如执行remove方法会将这些item为null的节点从链表中移除并重置head节点。

public E peek() {
        restartFromHead:
        for (;;) {
            //从head开始往后遍历,找到第一个item非空的节点,将该节点置为head
            for (Node<E> h = head, p = h, q;;) {
                E item = p.item;
                //如果item不为空或者p就是最后一个节点了,就将head置为p,原来的head从链表中移除了
                //执行poll方法会将item置为null而不从链表中移除
                if (item != null || (q = p.next) == null) {
                    //将p置为head,之前item为null的节点就从链表中移除了
                    updateHead(h, p);
                    return item;
                }
                else if (p == q) //p等于q说明这个节点已下线,有了新的head节点
                    continue restartFromHead; //重新开始外层的for循环,从head节点开始重新遍历
                else
                    p = q; //处理下一个节点
            }
        }
    }

public E poll() {
        restartFromHead:
        for (;;) {
            for (Node<E> h = head, p = h, q;;) {
                E item = p.item;
                //如果item不为null,将item属性置为null
                if (item != null && p.casItem(item, null)) {
                    //如果没有并行修改p的item属性,则head节点不会变更,即存在多个节点的item属性为null的情形
                    if (p != h) 
                        //第一遍cas修改失败,即有其他线程在并行的poll,p变成下一个节点,再for循环p就不等于h了,
                        //此时cas成功就需要将head属性修改为p的下一个节点,将此前的两个节点都从链表中移除,如果p就是最后一个节点了则修改为p
                        updateHead(h, ((q = p.next) != null) ? q : p);
                    return item;
                }
                //如果item为null或者casItem失败了
                else if ((q = p.next) == null) { //如果p是最后一个节点了
                    updateHead(h, p);
                    return null;
                }
                else if (p == q) //如果p已下线,则从head重新开始
                    continue restartFromHead;
                else
                    //处理下一个节点
                    p = q;
            }
        }
    }

public boolean remove(Object o) {
        if (o != null) {
            Node<E> next, pred = null;
            //first方法返回第一个item不为空的节点并且会调整head
            for (Node<E> p = first(); p != null; pred = p, p = next) {
                boolean removed = false;
                E item = p.item;
                if (item != null) {
                    if (!o.equals(item)) {
                        //不是目标节点,获取下一个有效节点,继续遍历
                        next = succ(p);
                        continue;
                    }
                    //如果找到目标节点了,将对应节点的item属性置为null
                    removed = p.casItem(item, null);
                }
                //如果item为null或者找到了目标节点
                next = succ(p);
                if (pred != null && next != null) //将p从链表中移除,如果p就是head节点,此时next为null,则通过下一次的first方法移除
                    pred.casNext(p, next);
                if (removed)
                    //移除,返回true
                    return true;
            }
        }
        return false;
    }



//h不等于p的情况下才会更新head
final void updateHead(Node<E> h, Node<E> p) {
        if (h != p && casHead(h, p))
            h.lazySetNext(h); //修改成功,将next指向自己,表示这个节点已下线
    }

//原子的修改head属性
private boolean casHead(Node<E> cmp, Node<E> val) {
        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
    }

//返回第一个item不为null的节点,如果都是null,则返回null
Node<E> first() {
        restartFromHead:
        for (;;) {
            //从head节点往后遍历,会跳过前面item为null的节点,将第一个item不为null的节点置为head节点并返回
            for (Node<E> h = head, p = h, q;;) {
                boolean hasItem = (p.item != null);
                if (hasItem || (q = p.next) == null) {
                    //如果item不为null 或者p是最后一个节点
                    updateHead(h, p);
                    return hasItem ? p : null;
                }
                else if (p == q)
                    continue restartFromHead;
                else
                    p = q;
            }
        }
    }

final Node<E> succ(Node<E> p) {
        Node<E> next = p.next;
        //p等于next该节点已下线,返回head节点,从head开始重新遍历,否则返回next节点
        return (p == next) ? head : next;
    }

5、iterator / Itr

      通过Itr移除节点时,一样的不会将该节点从链表中移除,只是将item属性置为null。

public Iterator<E> iterator() {
        return new Itr();
    }

private class Itr implements Iterator<E> {
        //下一次next方法对应的节点
        private Node<E> nextNode;

        //下一次next方法返回的元素
        private E nextItem;

        //上一次next方法返回的节点
        private Node<E> lastRet;

        Itr() {
            advance();
        }
      
        private E advance() {
            lastRet = nextNode;
            E x = nextItem;

            Node<E> pred, p;
            if (nextNode == null) {
                //nextNode为null,由构造方法调用的
                //将p赋值成第一个item非空的节点
                p = first();
                pred = null;
            } else {
                //nextNode不为null,由next方法调用
                pred = nextNode;
                //获取下一个有效节点
                p = succ(nextNode);
            }

            for (;;) {
                if (p == null) {
                    //链表为空或者已经遍历完所有节点了
                    nextNode = null;
                    nextItem = null;
                    return x;
                }
                E item = p.item;
                if (item != null) {
                    //不为null,nextNode和nextItem重新赋值,返回之前的nextItem
                    nextNode = p;
                    nextItem = item;
                    return x;
                } else {
                    //item为null,会通过for循环跳过所有为null的节点,将他们从链表中移除
                    Node<E> next = succ(p);
                    if (pred != null && next != null)
                        pred.casNext(p, next);
                    p = next;
                }
            }
        }

        public boolean hasNext() {
            return nextNode != null;
        }

        public E next() {
            if (nextNode == null) throw new NoSuchElementException();
            return advance();
        }

        public void remove() {
            Node<E> l = lastRet;
            if (l == null) throw new IllegalStateException();
            //将对应节点的item属性置为null即可
            l.item = null;
            lastRet = null;
        }
    }

二、LinkedTransferQueue

 1、定义

     LinkedTransferQueue的类继承关系如下:

TransferQueue接口继承自BlockingQueue接口,添加了如下方法:

后面会详细介绍这些方法的用途。该类包含的属性如下:

//是否多核系统
private static final boolean MP =
        Runtime.getRuntime().availableProcessors() > 1;
//如果前一个节点已匹配,下一个匹配的就是当前节点,则最多自旋FRONT_SPINS次,
private static final int FRONT_SPINS   = 1 << 7;
//前面节点在自旋等待时自旋的最大次数,即前面一个节点可能很快会匹配,
private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;
//sweepVotes超过这个阈值就会执行sweep方法,将链表中所有已匹配节点都删除掉
static final int SWEEP_THRESHOLD = 32;

//NOW表示无限期等待
private static final int NOW   = 0; // for untimed poll, tryTransfer
//ASYNC表示不需要等待
private static final int ASYNC = 1; // for offer, put, add
private static final int SYNC  = 2; // for transfer, take
//TIMED表示有期限等待
private static final int TIMED = 3; // for timed poll, tryTransfer

/** 队列头节点 */
transient volatile Node head;

/** 队列尾节点 */
private transient volatile Node tail;

/**触发清理的累计次数 */
private transient volatile int sweepVotes;

除此之外,还有几个表示属性偏移量的属性,通过static代码块初始化,如下:

上述属性中的Node是一个静态内部类,表示队列中的一个节点,其实现如下:

static final class Node {
        //为true表示当前操作是put类型
        final boolean isData;   // false if this is a request node
        //关联的元素
        volatile Object item;   // initially non-null if isData; CASed to match
        //下一个节点
        volatile Node next;
        //执行操作的线程
        volatile Thread waiter; // null until waiting

        //cas修改next属性
        final boolean casNext(Node cmp, Node val) {
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
        }

        //cas修改item属性
        final boolean casItem(Object cmp, Object val) {
            // assert cmp == null || cmp.getClass() != Node.class;
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
        }

    
        Node(Object item, boolean isData) {
            UNSAFE.putObject(this, itemOffset, item); // relaxed write
            this.isData = isData;
        }

        //让next属性指向自己,将该节点标记为一个无效节点
        final void forgetNext() {
            UNSAFE.putObject(this, nextOffset, this);
        }

        //item属性指向自己,waiter属性置为null,表示这是一个已匹配的节点
        final void forgetContents() {
            UNSAFE.putObject(this, itemOffset, this);
            UNSAFE.putObject(this, waiterOffset, null);
        }

        //为true表示该节点已经匹配过了
        final boolean isMatched() {
            Object x = item;
            return (x == this) || ((x == null) == isData);
        }

        //判断当前节点是否是一个未匹配的请求数据的节点
        final boolean isUnmatchedRequest() {
            return !isData && item == null;
        }

        //如果某个节点不能插入到当前节点的后面则返回true
        final boolean cannotPrecede(boolean haveData) {
            boolean d = isData;
            Object x;
            //当前节点未匹配且两个节点的操作类型不一致时返回true
            return d != haveData && (x = item) != this && (x != null) == d;
        }

    
        final boolean tryMatchData() {
            // assert isData;
            Object x = item;
            if (x != null && x != this && casItem(x, null)) {
                 //将item修改为null,唤醒关联的线程
                 //put类操作永远不会等待,waiter始终为null
                 //take类操作节点如果匹配成功,item属性也不会null,但是匹配成功后也会将waiter置为null,所以此处的unpark没有太大意义
                LockSupport.unpark(waiter);
                return true;
            }
            return false;
        }

        private static final long serialVersionUID = -3375979862319811754L;

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

2、add / offer / put

     下面4个方法的实现都是一样的,都是往链表中插入一个节点,因为是无固定容量的队列,所以永远不会出现因为队列满了而阻塞的情形。

public boolean add(E e) {
        xfer(e, true, ASYNC, 0);
        return true;
    }

public boolean offer(E e) {
        xfer(e, true, ASYNC, 0);
        return true;
    }

public boolean offer(E e, long timeout, TimeUnit unit) {
        xfer(e, true, ASYNC, 0);
        return true;
    }

 public void put(E e) {
        xfer(e, true, ASYNC, 0);
    }

3、take / poll /peek

public E take() throws InterruptedException {
        //无期限等待
        E e = xfer(null, false, SYNC, 0);
        if (e != null) 
            return e;
        //为null说明是因为线程中断导致的,将当前线程标记为中断并抛出异常    
        Thread.interrupted();
        throw new InterruptedException();
    }

public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        //等待一定的时间,如果超时或者被中断返回null
        E e = xfer(null, false, TIMED, unit.toNanos(timeout));
        if (e != null || !Thread.interrupted())
            return e;
        //线程被中断返回null,此处抛出异常    
        throw new InterruptedException();
    }

public E poll() {
        //如果之前有未匹配的put操作,则返回未匹配的最早的一个put操作,否则返回null,不会等待
        return xfer(null, false, NOW, 0);
    }

public E peek() {
        return firstDataItem();
    }

//获取链表中第一个未匹配的节点,如果是put类操作返回put的元素,如果是take操作返回null
private E firstDataItem() {
        for (Node p = head; p != null; p = succ(p)) {
            Object item = p.item;
            if (p.isData) {//如果p是put类操作
                if (item != null && item != p) //如果p未匹配,如果已匹配则继续for循环
                    return LinkedTransferQueue.<E>cast(item);
            }
            else if (item == null) //如果p是take类操作且未匹配则返回null,如果已匹配则继续for循环
                return null;
        }
        return null;
    }

//返回下一个有效节点,如果p等于next说明该节点已失效且该节点原来是head节点,则重新获取新的head节点
final Node succ(Node p) {
        Node next = p.next;
        return (p == next) ? head : next;
    }

 @SuppressWarnings("unchecked")
static <E> E cast(Object item) {
        // assert item == null || item.getClass() != Node.class;
        return (E) item;
    }

4、remove / drainTo

public boolean remove(Object o) {
        return findAndRemove(o);
    }

public int drainTo(Collection<? super E> c) {
        if (c == null)
            throw new NullPointerException();
        if (c == this)
            throw new IllegalArgumentException();
        int n = 0;
        //poll方法会返回之前未匹配的put操作的元素并将其从链表中移除
        //如果没有未匹配的put操作节点,则返回null
        for (E e; (e = poll()) != null;) {
            c.add(e);
            ++n;
        }
        return n;
    }

   
public int drainTo(Collection<? super E> c, int maxElements) {
        if (c == null)
            throw new NullPointerException();
        if (c == this)
            throw new IllegalArgumentException();
        int n = 0;
        for (E e; n < maxElements && (e = poll()) != null;) {
            c.add(e);
            ++n;
        }
        return n;
    }

private boolean findAndRemove(Object e) {
        if (e != null) {
            //从head节点开始往后遍历
            for (Node pred = null, p = head; p != null; ) {
                Object item = p.item;
                if (p.isData) { //p是put类操作
                    if (item != null && item != p && e.equals(item) &&
                        p.tryMatchData()) { //找到了目标节点且该节点未匹配
                        unsplice(pred, p); //将p从链表中移除
                        return true;
                    }
                }
                else if (item == null) //如果p是take类操作节点,说明链表中没有put类操作的节点了,直接终止循环
                    break;
                pred = p; 
                if ((p = p.next) == pred) { //p的next属性指向自己了,表示p是一个无效节点,从head开始重新遍历
                    pred = null;
                    p = head;
                }
                //遍历下一个节点
            }
        }
        return false;
    }

5、transfer / tryTransfer / getWaitingConsumerCount

     transfer和tryTransfer都是put类操作,跟上面put方法不同的是,这三个方法会阻塞当前线程,transfer会无限期阻塞,

//put类操作,会无限期等待
public void transfer(E e) throws InterruptedException {
        if (xfer(e, true, SYNC, 0) != null) { //返回非null表示因为中断而操作失败了
            Thread.interrupted(); //将当前线程标记为中断并抛出异常
            throw new InterruptedException();
        }
    }

//put类操作,等待指定的时间
public boolean tryTransfer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {
        if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null)
            return true;
        //因为等待超时返回非null,返回false
        if (!Thread.interrupted())
            return false;
         //因为中断导致,抛出异常
        throw new InterruptedException();
    }

public boolean tryTransfer(E e) {
        //如果之前有未匹配的take类操作则返回null,否则返回e
        return xfer(e, true, NOW, 0) == null;
    }

//统计take类操作的节点数
public int getWaitingConsumerCount() {
        return countOfMode(false);
    }

private int countOfMode(boolean data) {
        int count = 0;
        for (Node p = head; p != null; ) {
            if (!p.isMatched()) {
                //如果p未匹配,如果p的操作类型跟data不一致,链表中其他节点的操作类型一样不同
                //返回0 
                if (p.isData != data)
                    return 0;
                //如果相同,count+1,如果达到int的最大值则终止遍历
                if (++count == Integer.MAX_VALUE) // saturated
                    break;
            }
            //如果p已匹配
            Node n = p.next;
            if (n != p)
                p = n; //遍历下一个节点
            else {
                count = 0;//从head节点开始重新遍历 
                p = head;
            }
        }
        return count;
    }

6、xfer

     xfer方法是整个TransferQueue接口实现的核心,其实现跟SynchronousQueue中的用于实现FIFO模式的内部类TransferQueue类似,该方法的使用也跟transfer方法类似

//e表示当前操作的元素,如果take类操作则是null
//如果是put操作,haveData为true,否则为false
//调用的模式,一共有四种NOW, ASYNC, SYNC, or TIMED
//nanos表示等待的时间
private E xfer(E e, boolean haveData, int how, long nanos) {
        if (haveData && (e == null)) //参数非法,抛出异常
            throw new NullPointerException();
        Node s = null;                        // the node to append, if needed

        retry:
        for (;;) {                            // restart on append race
            //构造方法中不会初始化head和tail属性,这两个初始值为null
            for (Node h = head, p = h; p != null;) { // find & match first node
                boolean isData = p.isData;
                Object item = p.item;
                if (item != p && (item != null) == isData) { //如果p未匹配
                    if (isData == haveData)   //如果节点p和当前节点的操作类型一致,则终止循环,将其添加到队列中
                        break;
                    //节点p和当前节点的操作类型不一致,可以匹配    
                    if (p.casItem(item, e)) { //修改item为e,e可能为null或者某个元素,会与原来的item不同,表示这个节点已匹配
                        //修改成功,p和当前操作匹配 
                        for (Node q = p; q != h;) {
                            Node n = q.next;  // update by 2 unless singleton
                            //head节点没变,将head节点修改为q的下一个节点n,如果变了通过下面的if分支重新读取
                            //即正常情况下链表中不会有已匹配未删除的节点,只是在并发条件下很短暂的时间内可能出现
                            if (head == h && casHead(h, n == null ? q : n)) {
                                h.forgetNext(); //next属性指向自己,从链表中移除,然后终止内存for循环
                                break;
                            } 
                            //如果head节点变了或者上面casHead修改失败
                            //head节点为null或者只有head一个节点了时需要终止for循环,因为没有next节点了
                            //q未匹配节点时也需要终止,因为该节点未匹配,不能从链表中移除,此时其他线程已经完成head节点的变更了
                            //上述条件不成立,则下一次for循环时head会等于h,会重新casHead
                            if ((h = head)   == null ||
                                (q = h.next) == null || !q.isMatched())
                                break;        // unless slack < 2
                        }
                        //唤醒p对应的线程,唤醒后p发现自己已匹配,会将item属性指向自己,waiter属性置为null
                        LockSupport.unpark(p.waiter);
                        //返回item属性,如果是put操作则返回null,如果是take操作则返回对应put操作节点的元素
                        return LinkedTransferQueue.<E>cast(item);
                    }
                }
                //如果p已匹配,获取p的下一个节点
                Node n = p.next;
                //如果p等于n,即p节点是无效的,则从head重新遍历,否则p等于n,即遍历下一个节点
                p = (p != n) ? n : (h = head); // Use head if p offlist
            }

            if (how != NOW) {                 // No matches available
                if (s == null)
                    s = new Node(e, haveData); //创建一个新节点
                Node pred = tryAppend(s, haveData); //将新节点插入到链表中
                if (pred == null)  //如果当前节点不能插入到链表最后一个节点的后面则返回null,外层for循环重试
                    continue retry;           // lost race vs opposite mode
                if (how != ASYNC)
                    //执行等待
                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
            }
            //如果等于NOW则直接返回,不会创建新节点或者等待
            return e; // not waiting
        }//外层for循环结束
    }

private Node tryAppend(Node s, boolean haveData) {
        for (Node t = tail, p = t;;) {        // move p to last node and append
            Node n, u;                        // temps for reads of next & tail
            if (p == null && (p = head) == null) {
                //链表未初始化,将head由null改成s
                if (casHead(null, s))
                    return s;                 // initialize
            }
            //tail为null,head不为null 或者tail不为null时进入下面的逻辑
            else if (p.cannotPrecede(haveData)) //如果节点s不能插入到p的后面
                return null;                  // lost race vs opposite mode
            else if ((n = p.next) != null)    //如果p的下一个节点不为空
                //初始状态下p等于t的,此时p就等于n,p就不等于t了,下一次for循环直接接入else分支
                //p的next节点不为空时,如果casNext修改失败,即有其他线程并行修改next,再次for循环,p就不等于t了,这时将p置为最新的tail节点
                p = p != t && t != (u = tail) ? (t = u) : // stale tail
                    (p != n) ? n : null;      // restart if off list
            //原子的修改p的next属性,p实际就是tail节点,即新节点是插入到链表的末尾        
            else if (!p.casNext(null, s)) //p的下一个节点不为null或者并行修改next属性都可能导致cas修改失败
                p = p.next;                   //cas修改p的next属性失败,将p置为p的next节点,此时p就不等于t了
            else {
                //上述casNext操作成功
                //head不为null,tail为null时,p被赋值成head,p就不等于t了,tail还是t,通过casTail将tail修改为p
                //head和tail都不为null时,上面的p.next不为空或者casNext修改失败,p变成p的下一个节点了,下一次for循环再次casNext后进入此分支
                //即此时tail后面肯定有两个非空的节点
                if (p != t) { 
                //如果tail发生了改变了直接执行后面的条件,重新读取tail,读取tail的后的第二个节点
                //下一次的while循环tail就等于t了,执行后面的casTail,将第二个节点置为新的tail,如果修改失败说明tail又变了
                //重新读取tail,直到修改tail成功           
                    while ((tail != t || !casTail(t, s)) &&  
                           (t = tail)   != null &&
                           (s = t.next) != null && // advance and retry
                           (s = s.next) != null && s != t);
                }
                return p;
            }
        }
    }

 private boolean casTail(Node cmp, Node val) {
        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
    }

//pred是s的前一个节点
 private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
        //计算等待的终止时间
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        Thread w = Thread.currentThread();
        int spins = -1; // initialized after first item and cancel checks
        ThreadLocalRandom randomYields = null; // bound if needed

        for (;;) {
            Object item = s.item;
            if (item != e) {  //如果该节点已经匹配其他节点了,正常流程
                // assert item != s;
                s.forgetContents();  //将item属性指向自己,waiter属性置为null
                //返回item,如果当前节点是put类操作则返回null,是take类操作则返回配对的put操作的item
                return LinkedTransferQueue.<E>cast(item);
            }
            //线程被中断,不需要等待或者等待超时,将item指向它自己
            if ((w.isInterrupted() || (timed && nanos <= 0)) &&
                    s.casItem(e, s)) { //将item属性指向自己
                unsplice(pred, s);//将s从链表中移除,同时会将head节点后一部分已匹配的节点移除
                //操作失败时,返回当前操作的元素,如果是take类操作返回null,如果是put类操作返回非null
                return e;
            }

            if (spins < 0) {  //判断是否需要自旋
                if ((spins = spinsFor(pred, s.isData)) > 0) 
                    randomYields = ThreadLocalRandom.current(); //如果需要自旋,初始化randomYields
            }
            else if (spins > 0) { //执行自旋
                --spins; 
                if (randomYields.nextInt(CHAINED_SPINS) == 0)
                    Thread.yield();           //如果返回的随机值等于0则执行yeild
            }
            //自旋等待结束了
            else if (s.waiter == null) {
                s.waiter = w;                 //保存waiter
            }
            //执行等待,如果被唤醒,则重新执行for循环
            else if (timed) {
                //等待指定的时间 
                nanos = deadline - System.nanoTime();
                if (nanos > 0L)
                    LockSupport.parkNanos(this, nanos);
            }
            else {
                //无期限等待
                LockSupport.park(this);
            }
        }
    }

final void unsplice(Node pred, Node s) {
        s.forgetContents(); //将next属性指向自己,waiter属性置为null
        if (pred != null && pred != s && pred.next == s) {
            //如果s还是pred的下一个节点
            Node n = s.next;
            if (n == null || //如果s就是最后一个节点
                (n != s && pred.casNext(s, n) && pred.isMatched())) { //pred的next修改为n且pred已匹配,如果pred未匹配则不用执行下面的清理逻辑了
                //从head往后遍历跳过前面已匹配的节点,将他们从链表中移除,直到找到第一个未匹配的节点或者遍历到pred了
                for (;;) {               // check if at, or could be, head
                    Node h = head;
                    if (h == pred || h == s || h == null) //h等于pred,因为pred是已经匹配过的,即pred前面的节点都已经被清除了不需要通过sweep清除了
                        return;          // at head or list empty
                    if (!h.isMatched()) //如果h未匹配,终止循环,在head和pred之间可能还有已经匹配过的节点,需要借助sweep方法清理
                        break;
                    //如果h已匹配    
                    Node hn = h.next;
                    if (hn == null)
                        return;          // hn为空,说明当前链表没有其他节点了,一夜不需要通过sweep清理了
                    //如果h的next属性没有指向它自己,将hn作为新的head,h的next属性指向自己,修改head的动作会将原来的head从链表中移除    
                    if (hn != h && casHead(h, hn)) 
                        h.forgetNext();  // advance head
                }
                if (pred.next != pred && s.next != s) { //如果pred和s节点的next属性都没有指向自己
                    for (;;) {           // sweep now if enough votes
                        int v = sweepVotes;
                        if (v < SWEEP_THRESHOLD) {
                            if (casSweepVotes(v, v + 1)) //原子的将sweepVotes加1,修改失败则重试
                                break;
                        }
                        //如果sweepVotes等于SWEEP_THRESHOLD了,将其置为0,执行sweep
                        else if (casSweepVotes(v, 0)) {
                            sweep();
                            break;
                        }
                    }
                }
            }
        }
    }

//清理掉所有已完成匹配的节点
 private void sweep() {
        //从head开始往后遍历,s是p的next节点
        for (Node p = head, s, n; p != null && (s = p.next) != null; ) {
            if (!s.isMatched())
                //如果s未匹配,p置为s,即处理下一个节点
                p = s;
            //s已匹配
            else if ((n = s.next) == null) //如果s是最后一个节点,终止遍历
                break;
            else if (s == n)    //即s的next属性指向它自己,该节点是一个无效节点,从head开始重新遍历
                p = head;
            else
                //s的下一个节点不为空且是正常节点,将p的next修改为n,即将s从链表中移除
                p.casNext(s, n);
        }
    }

private static int spinsFor(Node pred, boolean haveData) {
        if (MP && pred != null) {
            if (pred.isData != haveData)      //如果pred的操作类型和当前不同
                return FRONT_SPINS + CHAINED_SPINS;
            if (pred.isMatched())             //如果pred已匹配
                return FRONT_SPINS;
            if (pred.waiter == null)          //如果pred在自旋等待中
                return CHAINED_SPINS;
        }
        //如果是单核系统或者pred也在等待中
        return 0;
    }

7、iterator / Itr

public Iterator<E> iterator() {
        return new Itr();
    }

final class Itr implements Iterator<E> {
        private Node nextNode;   // next node to return item for
        private E nextItem;      // the corresponding item
        private Node lastRet;    // last returned node, to support remove
        private Node lastPred;   // predecessor to unlink lastRet

        /**
         * Moves to next node after prev, or first node if prev null.
         */
        private void advance(Node prev) {

            Node r, b; 
            //如果lastRet是未匹配的,则用lastPred保存lastRet
            if ((r = lastRet) != null && !r.isMatched())
                lastPred = r;    // next lastPred is old lastRet
            else if ((b = lastPred) == null || b.isMatched()) //如果lastPred为null或者已匹配,则将其置为null
                lastPred = null; // at start of list
            else {
                Node s, n;       // help with removal of lastPred.next
                //从b往后遍历把所有已匹配的节点移除直到链表末尾
                while ((s = b.next) != null && s != b && s.isMatched() &&  //b是有效节点且b的下一个节点已匹配
                       (n = s.next) != null && n != s) //b的下一个节点是有效的且下下一个节点非空
                    b.casNext(s, n); //将s从链表中移除
            }

            this.lastRet = prev;

            for (Node p = prev, s, n;;) {
                //构造方法调用advance方法时,prev为null
                s = (p == null) ? head : p.next;
                if (s == null)
                    break; //没有有效节点了,终止循环,将nextNode和nextItem都置为null
                else if (s == p) { //p是一个无效节点
                    p = null;
                    continue;
                }
                Object item = s.item;
                if (s.isData) {
                    //如果s是put类操作且未匹配,返回该节点
                    if (item != null && item != s) {
                        nextItem = LinkedTransferQueue.<E>cast(item);
                        nextNode = s;
                        return;
                    }
                }
                else if (item == null) //s是take类操作且未匹配,终止循环
                    break;
                //s是已匹配的节点
                if (p == null)
                    p = s; //prev是null是,p为null,将p赋值成s,继续处理s的下一个节点
                else if ((n = s.next) == null) //如果s是最后一个节点了,说明没有未匹配的节点了,终止循环
                    break;
                else if (s == n) //s是无效节点,重新从head开始遍历
                    p = null;
                else
                    p.casNext(s, n); //将s从链表中移除
            }
            nextNode = null;
            nextItem = null;
        }

        Itr() {
            advance(null);
        }

        public final boolean hasNext() {
            return nextNode != null;
        }

        public final E next() {
            Node p = nextNode;
            if (p == null) throw new NoSuchElementException();
            E e = nextItem;
            advance(p);
            return e;
        }

        public final void remove() {
            final Node lastRet = this.lastRet;
            if (lastRet == null)
                throw new IllegalStateException();
            this.lastRet = null;
            if (lastRet.tryMatchData())
                //将lastRet从链表中移除
                unsplice(lastPred, lastRet);
        }
    }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值