关于 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

posted @ 2021-10-22 14:52  TomStudio  阅读(161)  评论(0)    收藏  举报