使用受管理的阻止在ForkJoinPool中导致饥饿

在我的应用程序中,我以不同的速率向commonPool提交两种任务。

任务1:

ForkJoinPool.managedBlock(
//...
Uninterruptibles.putUninterruptibly(blockingQueueQithMaxSize50, "a")
//...
);

任务2:

List<String> list = Lists.newLinkedList();
ForkJoinPool.managedBlock(
//...
Queues.drainUninterruptibly(blockingQueueWithMaxSize50, list, 1, 1, SECONDS);
//...
);

在某些情况下,当task-1类型的任务提交给池的速率过高,并且blockingQueue已满时,运行task-1类型任务的所有线程都将对put进行阻塞(线程数大约是52)。 但是仍然提交给池的类型为task-1task-2的新任务不会导致在池中产生新的工作人员,这导致所有后续任务在导致饥饿和死锁的工作队列中排队导致应用冻结。

有人能帮我理解我在这里做错了吗?

经过一番挖掘,我发现这些:

  • ForkJoinPool并行度= 1个死锁
  • https://bugs.openjdk.java.net/browse/JDK-7035020
  • 但看起来这个bug在java 7本身中得到了修复。

    ENV:

  • JDK:oracle-j2sdk1.8 | 1.8.0 + update20
  • Arch:amd64
  • 操作系统:Debian Wheezy
  • 公共泳池配置:

  • 可用处理器= 2
  • 这意味着并行性= 1
  • 所有其他配置都是默认配置
  • 更新1

    一些更多信息:

    我将可运行内容submit给内部调用externalPush方法的ForkJoinPool

    final void externalPush(ForkJoinTask<?> task) {
        WorkQueue q; int m, s, n, am; ForkJoinTask<?>[] a;
        int r = ThreadLocalRandom.getProbe();
        int ps = plock;
        WorkQueue[] ws = workQueues;
        if (ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 &&
            (q = ws[m & r & SQMASK]) != null && r != 0 &&
            U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
            if ((a = q.array) != null &&
                (am = a.length - 1) > (n = (s = q.top) - q.base)) {
                int j = ((am & s) << ASHIFT) + ABASE;
                U.putOrderedObject(a, j, task);
                q.top = s + 1;                     // push on to deque
                q.qlock = 0;
                if (n <= 1)
                    signalWork(ws, q);
                return;
            }
            q.qlock = 0;
        }
        fullExternalPush(task);
    }
    

    当我进行远程调试时,执行到达

    q.top = s + 1; // push on to deque
    q.qlock = 0;
    if (n <= 1)
        signalWork(ws, q);
    return;
    

    但是n非常大,不小于或等于1,所以signalWork方法没有被调用,它一直调用tryAddWorker方法。

    链接地址: http://www.djcxy.com/p/35395.html

    上一篇: Starvation in ForkJoinPool with managed blocking

    下一篇: ExecutorService and ForkJoinPool