Skip to content

Commit b32cbe3

Browse files
committed
[Function add]
1.Add part of the conclusion of concurrentLinkedList.
1 parent be1df12 commit b32cbe3

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# ConcurrentLinkedQueue
2+
* ** 非阻塞**的链表队列
3+
* 通过CAS实现无锁非阻塞
4+
>基于链接节点的、无界的、线程安全。此队列按照 FIFO(先进先出)原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许 null 元素。
5+
6+
## Node
7+
* ConcurrentLinkedQueue的内部私有类
8+
* 使用了通过C++编写的Unsafe类
9+
```Java
10+
private static class Node<E> {
11+
volatile E item;
12+
volatile Node<E> next;
13+
/**
14+
* Constructs a new node. Uses relaxed write because item can
15+
* only be seen after publication via casNext.
16+
*/
17+
Node(E item) {
18+
UNSAFE.putObject(this, itemOffset, item);
19+
}
20+
boolean casItem(E cmp, E val) {
21+
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
22+
}
23+
void lazySetNext(Node<E> val) {
24+
UNSAFE.putOrderedObject(this, nextOffset, val);
25+
}
26+
boolean casNext(Node<E> cmp, Node<E> val) {
27+
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
28+
}
29+
// Unsafe mechanics
30+
private static final sun.misc.Unsafe UNSAFE;
31+
private static final long itemOffset;
32+
private static final long nextOffset;
33+
static {
34+
try {
35+
UNSAFE = sun.misc.Unsafe.getUnsafe();
36+
Class<?> k = Node.class;
37+
itemOffset = UNSAFE.objectFieldOffset
38+
(k.getDeclaredField("item"));
39+
nextOffset = UNSAFE.objectFieldOffset
40+
(k.getDeclaredField("next"));
41+
} catch (Exception e) {
42+
throw new Error(e);
43+
}
44+
}
45+
}
46+
```
47+
48+
## ConcurrentLinkedQueue's API
49+
* add() 通过offer方法添加元素。
50+
```Java
51+
public boolean add(E e) {
52+
return offer(e);
53+
}
54+
```
55+
56+
* offer()
57+
```Java
58+
public boolean offer(E e) {
59+
checkNotNull(e);
60+
final Node<E> newNode = new Node<E>(e);
61+
62+
for (Node<E> t = tail, p = t;;) {
63+
Node<E> q = p.next;
64+
if (q == null) {
65+
// p is last node
66+
if (p.casNext(null, newNode)) {
67+
// Successful CAS is the linearization point
68+
// for e to become an element of this queue,
69+
// and for newNode to become "live".
70+
if (p != t) // hop two nodes at a time
71+
casTail(t, newNode); // Failure is OK.
72+
return true;
73+
}
74+
// Lost CAS race to another thread; re-read next
75+
}
76+
else if (p == q)
77+
// We have fallen off list. If tail is unchanged, it
78+
// will also be off-list, in which case we need to
79+
// jump to head, from which all live nodes are always
80+
// reachable. Else the new tail is a better bet.
81+
p = (t != (t = tail)) ? t : head;
82+
else
83+
// Check for tail updates after two hops.
84+
p = (p != t && t != (t = tail)) ? t : q;
85+
}
86+
}
87+
```

0 commit comments

Comments
 (0)