概述
ConcurrentLinkedQueue是一种基于链表实现的无界非阻塞线程安全队列,遵循先入先出规则。
线程安全队列有两种实现方式:
阻塞方式:对入队和出队操作加锁。阻塞队列。
非阻塞方式:通过自旋CAS实现。例如:ConcurrentLinkedQueue
下面从源代码中分析ConcurrentLinkedQueue的实现方法。
类关系图
从类图可以看出,ConcurrentLinkedQueue有head和tail两个volatile域,节点是用静态内部类Node表示,每个Node含有元素item和指向下一个节点的指针next,都是volatile变量。
源码分析
Node源码
Node的item和next两个域都是volatile变量,保证可见性。casItem和casNext方法使用了UNSAFE提供的CAS方法保证操作的原子性。
1 //Node代码中使用了UNSAFE提供的CAS方法保证操作的原子性, 2 //UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); 3 //第一个参数表示要更新的对象,第二个参数nextOffset是Field的偏移量,第三个参数表示期望值,最后一个参数更新后的值。若next域的值等于cmp,则把next域更新为val并返回true;否则不更新并返回false。 4 private static class Node<E> { 5 volatile E item; //Node值,volatile保证可见性 6 volatile Node<E> next; //Node的下一个元素,volatile保证可见性 7 8 /** 9 * Constructs a new node. Uses relaxed write because item can 10 * only be seen after publication via casNext. 11 */ 12 Node(E item) { 13 UNSAFE.putObject(this, itemOffset, item); 14 } 15 16 boolean casItem(E cmp, E val) { 17 return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); 18 } 19 20 void lazySetNext(Node<E> val) { 21 UNSAFE.putOrderedObject(this, nextOffset, val); 22 } 23 24 boolean casNext(Node<E> cmp, Node<E> val) { 25 return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); 26 } 27 28 // Unsafe mechanics 29 30 private static final sun.misc.Unsafe UNSAFE; 31 private static final long itemOffset; 32 private static final long nextOffset; 33 34 static { 35 //初始化UNSAFE和各个域在类中的偏移量 36 try { 37 UNSAFE = sun.misc.Unsafe.getUnsafe();//初始化UNSAFE 38 Class k = Node.class; 39 //itemOffset是指类中item字段在Node类中的偏移量,先通过反射获取类的item域,然后通过UNSAFE获取item域在内存中相对于Node类首地址的偏移量。 40 itemOffset = UNSAFE.objectFieldOffset 41 (k.getDeclaredField("item")); 42 //nextOffset是指类中next字段在Node类中的偏移量 43 nextOffset = UNSAFE.objectFieldOffset 44 (k.getDeclaredField("next")); 45 } catch (Exception e) { 46 throw new Error(e); 47 } 48 } 49 }