关于 SynchronousQueue 原理文献
1、SynchronousQueue 源码
SynchronousQueue 中从BlockingQueue继承的put、offer、take、poll方法,内部都是调用 transferer.transfer 方法。
public class SynchronousQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable {
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
if (e == null) throw new NullPointerException();
if (transferer.transfer(e, true, unit.toNanos(timeout)) != null)
return true;
if (!Thread.interrupted())
return false;
throw new InterruptedException();
}
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
if (transferer.transfer(e, false, 0) == null) {
Thread.interrupted();
throw new InterruptedException();
}
}
public E take() throws InterruptedException {
E e = transferer.transfer(null, false, 0);
if (e != null)
return e;
Thread.interrupted();
throw new InterruptedException();
}
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
E e = transferer.transfer(null, true, unit.toNanos(timeout));
if (e != null || !Thread.interrupted())
return e;
throw new InterruptedException();
}
}
2、源码实现的自己理解的难点
① 当发现可以匹配后,不是和TransferQueue一样直接出来,而是以FullFilling节点入栈,而其他节点在入栈时发现栈顶是FullFilling节点时,也不能入栈,而是帮助FullFilling节点和next节点完成匹配,唤醒next线程。这样,就会导致,线程因发现FullFilling节点而不能及时入队,最终即使帮助FullFilling节点完成了匹配,唤醒了阻塞线程,但是下次进入循环时,依然不能保证能轮到他完成匹配
② 在else if (!isFulfilling(h.mode) && else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) 逻辑内部,即使前面的cas完成了,但是新节点 s后面的next节点,可能会由原来不是null,cas完成后不久后就是null了,主要原因是 一个节点入队后,会进行一段时间的自旋,自旋时若发现了线程被中断了,就会调用tryCancel操作,然后通过clean操作将自身清理,进而导致上述情况。
E transfer(E e, boolean timed, long nanos) {
SNode s = null; // constructed/reused as needed
int mode = (e == null) ? REQUEST : DATA;
for (;;) {
SNode h = head;
if (h == null || h.mode == mode) { // empty or same-mode
if (timed && nanos <= 0L) { // 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()) // 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
}
}
}
}
关于 SynchronousQueue原理---源码实现+基本思想:https://blog.csdn.net/weixin_43956062/article/details/106105889
java并发之SynchronousQueue实现原理:https://jishuin.proginn.com/p/763bfbd2945b
高度可靠系统,数据不再丢失?SynchronousQueue使用场景及实现:https://www.toutiao.com/a6651029973970715140/?log_from=afcb58fe1b753_1634743432816
浙公网安备 33010602011771号