Java并发包中并发队列原理
jdk中提供了一系列场景得并发安全队列,按实现方式的不同分为
- 阻塞队列
- 非阻塞队列
ConcurrentLinkedQueue简介
ConcurrentLinkedQueue是线程安全的无界非阻塞队列,用CAS实现
内部采用单向链表方式实现,首尾为2个volatile类型的Node节点用来存放队列的首尾节点。
public ConcurrentLinkedQueue(){
head=tail=new Node<E>(null);
}
通过无参构造器可以看出
- 默认头尾节点都是指向item为null的哨兵节点
- 新元素入队插入队列末尾
- 元素出队从队头出队
- Node节点内部维护一个使用volatile修饰的变量item,存放节点的值
- next用来存放链表的下一个节点,从而链接为一个单向无界链表
- 内部使用UNSafe工具提供的CAS算法保证出入队时操作链表的原子性
ConcurrentLinkedQueue操作源码解析
Offer操作
offer操作是在队列末尾添加一个元素,如果传递的参数为null则抛出NPE异常,因为ConcurrentLinkedQueue是无界队列,该方法将一直返回true。
另外,由于使用CAS无阻塞算法,该方法不会阻塞挂起调用线程
实现原理
public boolean contains(E e){
(1) e为null则抛出空指针异常
checkNotNull(e);
(2)构造Node节点,在构造函数内部调用unsafe.putObject
final Node<E> newNode=new Node<E>(e);
(3)从尾节点进行插入
for(Node<E> t=tail,p=t;;){
Node<E> q=p.next;
(4)
if(q==null){
(5)
if(p.casNext(null,newNode)){
(6)
if(p!=t){
casTail(t,newNode);
}
return true;
}
}else if(p==q){
(7)
p=(t!=(t=tail))?t:head;
}else{
p=(p!=t&&t!=(t=tail))?t:q;
}
}
}