ConcurrentLinkedQueue 1.8源码浅析

  (TOC)

  

ConcurrentLinkedQueue 1.8源码浅析

  
一、简介h5>   

ConcurrentlinkedQueue还是一个基于链表的,×××的,线程安全的单端队列,它采用先进先出(FIFO)的规则对节点进行排序,当我们加入一个元素时,它会插入队列的尾部,当我们获取元素时,会从队列的首部获取元素。它没有使用锁来保证线程安全,使用的是“<强>无等待强”算法来保证整个队列的线程安全。

     
二,基本成员简介h5> 节点节点对象   
 <代码类="语言java ">//存储的数据
  挥发性E项;//下一个节点引用
  挥发性Node下一个;/* *
  *构造一个新节点。使用放松因为项可以写
  *>私人瞬态波动Node头; 
  <编辑>尾尾节点   
 <代码类="语言java ">私人瞬态波动Node尾巴; 
  
三,常用方法解析
  <编辑>无参构造方法   
 <代码类="语言java ">公共ConcurrentLinkedQueue () {
  头=尾=new Node(空);
  } 
  

构造节点是其实就是构造了一个节点的项为零的节点,然后头和尾指向这个节点,如下图所示:

  

 ConcurrentLinkedQueue 1.8源码浅析

  <编辑>添加方法   
 <代码类="语言java ">公共逻辑加(E E) {
  返回提供(e);
  } 
  

我们可以看出其实调用的是提供方法,具体参考提供方法的讲解。

  <编辑>提供方法   

源码解析:

  
 <代码类="语言java ">公共布尔提供(E E) {//入队元素不能为null
  checkNotNull (e);//创建新的节点
  最后NodenewNode=new Node (e);//死循环,设置节点//p获取尾节点
  (Nodet=尾巴,p=t;;) {//q是p的下一节点
  Nodeq=p.next;//获取尾节点的下一节点//尾节点没有下一个节点
  如果(q==null) {//p是最后一个节点//这一步说明p是尾节点,新的节点设置为尾节点的下一节点
  如果(p。casNext (null, newNode)) {//成功的CAS是线性化点//e成为这个队列的一个元素,//和newNode成为“活”。//设置尾节点,当之前的尾节点和现在插入的节点之间有一个节点时//并不是每一次都cas设置尾节点(优化手段,是怎么想到这种优化的? ?)
  如果(p !=t)//跳两个节点//cas设置尾节点,可能会失败
  casTail (t, newNode);//失败是好的。
  返回true;
  }//CAS比赛输给了另一个线程;重读一
  }//多线程操作时候,由于投票时候会把旧的头变为自引用,然后将头部的未来设置为新的头//所以这里需要重新找新的头
  else if (p==)//我们有掉落列表。如果尾巴不变,它//也将off-list,在这种情况下我们需要//跳转到头部,所有节点都是生活//可及。其他新尾巴是一个更好的选择。
  p=(t !=(t=尾))?t:头;
  其他的//寻找尾节点//检查尾更新后两个啤酒花。//p !=t
  p=(p !=t,,t !=(t=尾))?t:问;
  }
  } 
  
  

分析插入过程,我们插入使用3个线程来调用提供方法,ThreadA, ThreadB同时运行,ThreadC最后插入,分析下提供方法的流程。

     

第一步,队列属于初始化状态,ThreadA, ThreadB同时调用提供方法;创建节点,死循环设置节点,获取尾节点的下一节点,此时问==null,两个线程都同时可能看的见,然后cas设置尾节点的下一节点(队列状态如图一所示),我们假设是ThreadA线程cas设置成功了,然后p==t此时的尾节点其实没有发生变化;此时我们来看ThreadB由于一个成功了,所以ThreadB cas失败了,重新循环,此时问!=零了,p==显然不等于,再看下一个别的判断p !=t,此时显然p==t,所以才是p=q,然后再次循环,此时的q==null,我们假设没有线程来和ThreadB竞争,所以中科院设置成功,然后p !=t吗,显然满足所以设置尾节点,此时的设置尾节点的节点和之前的尾节点之间刚刚好有一个节点(如图2所示)。

  

 ConcurrentLinkedQueue 1.8源码浅析

  

 ConcurrentLinkedQueue 1.8源码浅析

  

第二步,ThreadC插入,此时的尾节点是ThreadB插入的节点假设是B,获取B的下一节点,问==null,然后cas设置节点,完成,p==t,所以不用更新尾节点(如图C所示)。

  

 ConcurrentLinkedQueue 1.8源码浅析

ConcurrentLinkedQueue 1.8源码浅析