对ConcurrentLinkedQueue的源码的理解

1.简介

ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现,该算法在Michael & Scott算法上进行了一些修改。

2.offer()和add()方法
本质上offer和add是一样的。

 public boolean offer(E e) {
 		/*这里判断传的值是不是空值,如果是空值就会报空指针*/
        checkNotNull(e);
        /*创建一个节点*/
        final Node<E> newNode = new Node<E>(e);
        /*由于是做无锁的cas操作,这里对添加元素做自旋的操作。
		这里d两个变量t、p都指向尾节点*/
        for (Node<E> t = tail, p = t;;) {   					 <1>
            Node<E> q = p.next;
            
            if (q == null) {
            /*判断尾节点的下一个节点是不是空值,
            如果是空值,说明尾节点没有被修改,可以尝试做cas操作*/
                if (p.casNext(null, newNode)) {
            		/*如果成功了,就说明添加元素成功,
            		下面的判断是有可能另一个线程执行到步骤<1>的t = tail
            		,尾节点发生了变化,要对尾节点进行cas操作。*/
                    if (p != t) 
                        casTail(t, newNode); 
                    return true;
                }
            }
            else if (p == q)   									<2>
            /*这里是说如果在插入的过程中,其他线程执行了poll操作,
            导致了尾节点后移,有可能造成p==q,此时就要重新设置尾节点或者头结点。
            1:此时将新的尾节点和之前的尾节点进行比较,如果不相同,就说明之前的
            尾节点后移了,就要更新尾节点,然后再一次尝试插入操作。
            2:如果现在的尾节点和之前的尾节点相同,就说明头结点已经和尾节点重合了
            ,就要重新赋值头结点。*/
                p = (t != (t = tail)) ? t : head;
            else												<3>
            	/*如果都不是的话,就说明当前尾节点后面的元素不为空,
            	那就要将尾节点后移。
            	后移之前需要对尾节点做判断,排除尾节点和头结点重合,并且没有做
            	poll的操作改变尾节点。*/
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值