引言:
上两章中,我们一起学习了阻塞队列中的ArrayBlockingQueue,LinkedBlokingQueue和PriorityBlockingQueue和DelayQueue,本章,我们一起学习一下SynchronousQueue类。
SynchronousQueue 是同步阻塞队列类。队列中的容器使用栈和队列来实现,分别实现“非公平”和“公平”模式的同步队列。
SynchronousQueue简介:
同步阻塞队列,队列(或栈)内部只能包含少量元素,且插入元素的线程需要阻塞到接收元素的线程到来才能执行完成,反之亦然。
SynchronousQueue源码分析:
SynchronousQueue实现了两个内部类:TransferStack和TransferQueue类,基本所有操作都是由这两个类来处理,我们主要介绍的也是两个类的内容。
一,TransferStack类(非公平模式):
用于“非公平”模式,按照LIFO(后进先出)顺序存储元素的模式。
1.1 TransferStack类的基本元素
如下代码所示,SNode是构成栈的基础结构,由next,match,waiter,item,mode组成,分别表示下一个节点,匹配节点,请求的线程,数据的内容(如果是消费方则为null),节点模式。
其中mode(节点模式)主要有三种,如下:
static final int REQUEST= 0;//消费方的节点,表示在此请求一个数据
static final int DATA= 1;//生产方的节点,表示在提供一个数据
static final int FULFILLING= 2;//表示已经本节点已经和对应节点匹配上,马上要出栈
如图,REQUEST和DATA是消费方和生产方的请求节点,FULFILLING则表示一对已匹配的节点:
![a6299a03d42c01288308595d67a761c8.png](https://i-blog.csdnimg.cn/blog_migrate/9ced97a039832d13b8170388a4321668.jpeg)
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;
boolean casNext(SNodecmp, SNode val) {
return cmp == next &&
UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
//tryMatch方法用于匹配s与本节点,看是否匹配,如果匹配,则将等待线程的阻塞取消。
boolean tryMatch(SNode s) {
if(match == null &&
UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) {
Thread w = waiter;
if(w != null) {
waiter = null;
LockSupport.unpark(w);
}
return true;
}
return match == s;
}
// 节点取消,将match指向自身
void tryCancel() {
UNSAFE.compareAndSwapObject(this, matchOffset, null, this);
}
//判断是否是已取消的节点
boolean isCancelled() {
returnmatch == this;
}
}
volatile SNode head; //指向栈顶的节点
1.2 入队/出队操作逻辑
因出队/入队操作都使用transfer方法,直接对transfer方法进行分析即可。
如下代码所示,transfer方法将栈中的情况分为三种:
1.2.1 当前传入的模块是域栈顶模块相同(或者栈为空也是一样)。如下图
则当前节点入栈,等待匹配到对应的节点
![c79aa2d9fe007205712fe6e6913dec0d.png](https://i-blog.csdnimg.cn/blog_migrate/44ea7e0597a5d2f9215fe0eb6d2edf3e.jpeg)
1.2.2 当前传入的模块与栈顶模块匹配,达成交付操作。如下图
将一个FULFILLING节点入栈,找到对应的匹配节点,并将它们出栈
![510d56bb24f79a13b116aff2529aad61.png](https://i-blog.csdnimg.cn/blog_migrate/4fa736a9558a745fadb11dd2ba768ab1.jpeg)
1.2.3 当前栈顶的模块是匹配模块需要删除。如下图
找到对应的匹配节点,并将它们出栈
![26535447f6a314a7776f2f17da1e0c68.png](https://i-blog.csdnimg.cn/blog_migrate/f7e6814fe01d33a51b9de80d4ace9809.jpeg)
代码如下所示:
E transfer(E e, boolean timed, long nanos) {
SNodes = null; // constructed/reused as needed
int mode = (e == null) ? REQUEST: DATA;
for (;;) {
SNode h = head;
if(h == null || h.mode == mode) { //情况1
if(timed && nanos <= 0) { // can't wait
if(h != null && h.isCancelled())
casHead(h, h.next); // pop cancelled node
else
return null;
} 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()) 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)) //情况2
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 { //情况3 help a fulfiller
SNode m = h.next; // m is h's match
if(m == null) casHead(h, null);
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
}
}
}
}
1、线程data1执行情况1,由于当前没有配对的消费方线程,所以data1线程入栈,自旋后睡眠等待
2、线程data2再次执行了情况1,data2线程入栈,自旋一小会后睡眠等待。
3、来了一个线程req1,执行了情况2,发现栈顶为data2线程,互相匹配成功,会先把req1线程入栈,然后req1线程循环执行匹配put2线程逻辑,把栈顶指针直接指向 req1线程,就是将data2和req1出栈。
4、再来一个线程req2,执行情况2操作,req2线程入栈,在循环中匹配data1线程,最终全部匹配完毕,栈变为空,恢复初始状态。
二,TransferQueue类(公平模式):
用于“公平”模式,按照FIFO(先进先出)顺序存储元素的模式。
时间关系,后续章节学习。