概述

  ConcurrentLinkedQueue是一种基于链表实现的无界非阻塞线程安全队列,遵循先入先出规则。

  线程安全队列有两种实现方式:

    阻塞方式:对入队和出队操作加锁。阻塞队列。

    非阻塞方式:通过自旋CAS实现。例如:ConcurrentLinkedQueue

  下面从源代码中分析ConcurrentLinkedQueue的实现方法。

类关系图

      Java并发容器--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         }
View Code

相关文章: