ConcurrentLinkedQueue原理

934 阅读1分钟

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;
        }
    }
}