SynchronousQueue 源码分析

1
2
3
4
5
6
7
8
9
10
java复制代码// CPU的数量
static final int NCPUS = Runtime.getRuntime().availableProcessors();
// 有超时的情况自旋多少次,当CPU数量小于2的时候不自旋
static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32;
// 没有超时的情况自旋多少次
static final int maxUntimedSpins = maxTimedSpins * 16;
// 针对有超时的情况,自旋了多少次后,如果剩余时间大于1000纳秒就使用带时间的LockSupport.parkNanos()这个方法
static final long spinForTimeoutThreshold = 1000L;
// 传输器,即两个线程交换元素使用的东西
private transient volatile Transferer<E> transferer;

以栈方式实现的Transferer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
java复制代码static final class TransferStack<E> extends Transferer<E> {
// 栈中节点的几种类型:
// 1. 消费者(请求数据的)
static final int REQUEST = 0;
// 2. 生产者(提供数据的)
static final int DATA = 1;
// 3. 二者正在匹配中
static final int FULFILLING = 2;

// 栈中的节点
static final class SNode {
// 下一个节点
volatile SNode next; // next node in stack
// 匹配者
volatile SNode match; // the node matched to this
// 等待着的线程
volatile Thread waiter; // to control park/unpark
// 元素
Object item; // data; or null for REQUESTs
// 模式,也就是节点的类型,是消费者,是生产者,还是正在匹配中
// 其实就是判断 是消费者节点还是生产者节点
int mode;
}
// 栈的头节点
volatile SNode head;
}

以队列方式实现的Transferer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
java复制代码static final class TransferQueue<E> extends Transferer<E> {
// 队列中的节点
static final class QNode {
// 下一个节点
volatile QNode next; // next node in queue
// 存储的元素
volatile Object item; // CAS'ed to or from null
// 等待着的线程
volatile Thread waiter; // to control park/unpark
// 是否是数据节点
final boolean isData;
}

// 队列的头节点
transient volatile QNode head;
// 队列的尾节点
transient volatile QNode tail;
}

transfer 栈的方式 入栈 参数e 表示放入的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
scss复制代码E transfer(E e, boolean timed, long nanos) {


SNode s = null;
// 判断方法是执行take 还是put
int mode = (e == null) ? REQUEST : DATA;
// 1 入栈 0 出栈

for (;;)
{
SNode h = head;
// 空栈
if (h == null || h.mode == mode) // empty or same-mode
{
if (timed && nanos <= 0) // can't wait
{
if (h != null && h.isCancelled())
casHead(h, h.next); // pop cancelled node
else
return null;
}
// 走到这里表示是空栈 没有设置超时 cas 乐观锁把head 指向栈顶元素
// e 放入的数据 Mode 1 生产 0 消费 h栈顶元素
// 新加入的元素成为了新的栈顶元素
else if (casHead(h, s = snode(s, e, h, mode)))
{
SNode m = awaitFulfill(s, timed, nanos);
if (m == s)
{ // wait was cancelled
clean(s);
return null;
}
if ((h = head) != null && h.next == s)
casHead(h, s.next); // help s's fulfiller
return (E) ((mode == REQUEST) ? m.item : s.item);
}
}
else if (!isFulfilling(h.mode)) { // try to fulfill
if (h.isCancelled()) // already cancelled
casHead(h, h.next); // pop and retry
else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
for (;;) { // loop until matched or waiters disappear
SNode m = s.next; // m is s's match
if (m == null) { // all waiters are gone
casHead(s, null); // pop fulfill node
s = null; // use new node next time
break; // restart main loop
}
SNode mn = m.next;
if (m.tryMatch(s)) {
casHead(s, mn); // pop both s and m
return (E) ((mode == REQUEST) ? m.item : s.item);
} else // lost match
s.casNext(m, mn); // help unlink
}
}
} else { // help a fulfiller
SNode m = h.next; // m is h's match
if (m == null) // waiter is gone
casHead(h, null); // pop fulfilling node
else {
SNode mn = m.next;
if (m.tryMatch(h)) // help match
casHead(h, mn); // pop both h and m
else // lost match
h.casNext(m, mn); // help unlink
}
}
}
}

snode 构造元素

1
2
3
4
5
6
7
8
9
10
ini复制代码static SNode snode(SNode s, Object e, SNode next, int mode) 
{
if (s == null) s = new SNode(e);
//添加还是消费
s.mode = mode;
// 新的元素next 指向加入前的栈顶元素
s.next = next;
// 返回新元素
return s;
}

awaitFulfill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
java复制代码// 三个参数:需要等待的节点,是否需要超时,超时时间
SNode awaitFulfill(SNode s, boolean timed, long nanos) {
// 到期时间
final long deadline = timed ? System.nanoTime() + nanos : 0L;
// 当前线程
Thread w = Thread.currentThread();
// 自旋次数
int spins = (shouldSpin(s) ?
(timed ? maxTimedSpins : maxUntimedSpins) : 0);
for (;;) {
// 当前线程中断了,尝试清除s
if (w.isInterrupted())
s.tryCancel();

// 检查s是否匹配到了元素m(有可能是其它线程的m匹配到当前线程的s)
SNode m = s.match;
// 如果匹配到了,直接返回m
if (m != null)
return m;

// 如果需要超时
if (timed) {
// 检查超时时间如果小于0了,尝试清除s
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {
s.tryCancel();
continue;
}
}
if (spins > 0)
// 如果还有自旋次数,自旋次数减一,并进入下一次自旋
spins = shouldSpin(s) ? (spins-1) : 0;

// 后面的elseif都是自旋次数没有了
else if (s.waiter == null)
// 如果s的waiter为null,把当前线程注入进去,并进入下一次自旋
s.waiter = w; // establish waiter so can park next iter
else if (!timed)
// 如果不允许超时,直接阻塞,并等待被其它线程唤醒,唤醒后继续自旋并查看是否匹配到了元素
LockSupport.park(this);
else if (nanos > spinForTimeoutThreshold)
// 如果允许超时且还有剩余时间,就阻塞相应时间
LockSupport.parkNanos(this, nanos);
}
}

// SNode里面的方向,调用者m是s的下一个节点
// 这时候m节点的线程应该是阻塞状态的
boolean tryMatch(SNode s) {
// 如果m还没有匹配者,就把s作为它的匹配者
if (match == null &&
UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) {
Thread w = waiter;
if (w != null) { // waiters need at most one unpark
waiter = null;
// 唤醒m中的线程,两者匹配完毕
LockSupport.unpark(w);
}
// 匹配到了返回true
return true;
}
// 可能其它线程先一步匹配了m,返回其是否是s
return match == s;
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%