ConcurrentLinkedQueue源码阅读

//非阻塞,一个基于链接节点的无界线程安全队列
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
        implements Queue<E>, java.io.Serializable {
    private static final long serialVersionUID = 196745693267521676L;
    //头节点
    private transient volatile Node<E> head;
    //尾结点
    private transient volatile Node<E> tail;

    //链表节点
    private static class Node<E> {
        volatile E item;//元素
        volatile Node<E> next;//后继节点

        Node(E item) {
            UNSAFE.putObject(this, itemOffset, item);
        }

        boolean casItem(E cmp, E val) {
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
        }
        // 设置next域的值,并不会保证修改对其他线程立即可见
        void lazySetNext(Node<E> val) {
            UNSAFE.putOrderedObject(this, nextOffset, val);
        }
        // 比较并替换next域的值
        boolean casNext(Node<E> cmp, Node<E> val) {
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
        }
    }

    /**
     * Tries to CAS head to p. If successful, repoint old head to itself
     * as sentinel for succ(), below.
     */
    final void updateHead(Node<E> h, Node<E> p) {
        if (h != p && casHead(h, p))
            h.lazySetNext(h);//h的next域指向它自己
    }

    /**
     * Returns the successor of p, or the head node if p.next has been
     * linked to self, which will only be true if traversing with a
     * stale pointer that is now off the list.
     */
    final Node<E> succ(Node<E> p) {
        Node<E> next = p.next;
        return (p == next) ? head : next;
    }

    /**
     * 如果tail节点的next节点不为空,则将入队节点设置成tail节点,
     * 如果tail节点的next节点为空,则将入队节点设置成tail的next节点,
     * 所以tail节点不总是尾节点.
     */
    //在队列尾插入元素
    public boolean offer(E e) {
        checkNotNull(e);//元素非null
        final Node<E> newNode = new Node<E>(e);

        for (Node<E> t = tail, p = t;;) {
            Node<E> q = p.next;
            if (q == null) {//p为尾结点
                //p节点的next域指向newNode
                if (p.casNext(null, newNode)) {
                    if (p != t)
                        casTail(t, newNode);
                    return true;
                }
            }
            else if (p == q)
                p = (t != (t = tail)) ? t : head;
            else
                // Check for tail updates after two hops.
                //p == t --> p = q 否则尾结点被其他线程修改 p = tail
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

    //获取队列头节点并删除
    public E poll() {
        restartFromHead:
        for (;;) {
            for (Node<E> h = head, p = h, q;;) {
                E item = p.item;
                // item不为null并且比较并替换item成功
                if (item != null && p.casItem(item, null)) {
                    if (p != h)//表头发生变化,更新表头
                        updateHead(h, ((q = p.next) != null) ? q : p);
                    return item;
                } // 表头的下一个节点为null,即链表只有一个“内容为null的表头节点”。则更新表头为p,并返回null
                else if ((q = p.next) == null) {
                    updateHead(h, p);
                    return null;
                }
                else if (p == q)
                    continue restartFromHead;
                else
                    p = q;
            }
        }
    }

    //从队列中移除指定元素
    public boolean remove(Object o) {
        if (o == null) return false;
        Node<E> pred = null;
        // 获取第一个存活的结点
        for (Node<E> p = first(); p != null; p = succ(p)) {
            E item = p.item;
            // 找到item相等的结点,并且将该结点的item设置为null
            if (item != null &&
                o.equals(item) &&
                p.casItem(item, null)) {
                Node<E> next = succ(p);
                if (pred != null && next != null)
                    pred.casNext(p, next);
                return true;
            }
            pred = p;
        }
        return false;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值