【发布时间】:2015-08-04 05:50:48
【问题描述】:
这个小代码 sn-p 在 jdk8u45 上永远不会完成,而过去在 jdk8u20 上可以正常完成:
public class TestForkJoinPool {
final static ExecutorService pool = Executors.newWorkStealingPool(8);
private static volatile long consumedCPU = System.nanoTime();
public static void main(String[] args) throws InterruptedException {
final int numParties = 100;
final Phaser p = new Phaser(1);
final Runnable r = () -> {
p.register();
p.arriveAndAwaitAdvance();
p.arriveAndDeregister();
};
for (int i = 0; i < numParties; ++i) {
consumeCPU(1000000);
pool.submit(r);
}
while (p.getArrivedParties() != numParties) {}
}
static void consumeCPU(long tokens) {
// Taken from JMH blackhole
long t = consumedCPU;
for (long i = tokens; i > 0; i--) {
t += (t * 0x5DEECE66DL + 0xBL + i) & (0xFFFFFFFFFFFFL);
}
if (t == 42) {
consumedCPU += t;
}
}
}
Phasers 也可以被 ForkJoinPool 中执行的任务使用,这将确保在其他人被阻塞等待阶段推进时执行任务有足够的并行性。
但是javadoc of ForkjoinPool#mangedBlock 声明:
如果在 ForkJoinPool 中运行,可以先扩展池以确保足够的并行度
那里只有一个可能。所以我不确定这是否是一个错误,或者只是不依赖 Phaser/ForkJoinPool 合约的错误代码:Phaser/ForkJoinPool 组合的合约有多难防止死锁?
我的配置:
- Linux adc 3.14.27-100.fc19.x86_64 #1 SMP Wed Dec 17 19:36:34 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
- 8 核 i7
【问题讨论】:
-
@AlekseyShipilev 也许对这个问题有更多的见解:如果我删除 comsumeCpu() 部分,或者减少令牌的数量,测试会正确完成。如果我在 ForkJoinPool#tryCompensate 中设置断点并手动执行,则同样的情况
标签: java java-8 phaser forkjoinpool