次の小さなコード スニペットは、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;
}
}
}
フェイザーのドキュメントには、次のように記載されています
Phaser は、ForkJoinPool で実行されているタスクでも使用できます。これにより、フェーズが進むのを待っている他のタスクがブロックされている場合に、タスクを実行するのに十分な並列性が保証されます。
ただし、ForkjoinPool#mangedBlock の javadoc には次のように記載されています。
ForkJoinPool で実行している場合は、最初にプールを拡張して、十分な並列性を確保することができます
そこにあるのは5月だけです。したがって、これがバグなのか、それとも 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