我有一个奇怪的僵局,似乎只发生在main()
之外。
static
{
init();
}
private static final void init()
{
ForkJoinPool forkJoinPool = null;
try
{
forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
/*A*/ List<Void> list = new ArrayList<>();
for (int i = 0; i < 100; i++) list.add(null);
Object obj = forkJoinPool.submit(() ->
{
list.stream().parallel().forEach(t ->
{
/*B*/ System.err.println(1);
});
return null;
}).get();
System.out.println("no deadlock: " + obj);
}
catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
finally
{
if (forkJoinPool != null)
{
forkJoinPool.shutdown();
}
}
}
上面的代码有两个结果。
- 如果我在
/*A*/
处设置了一个断点,然后恢复执行,那么它将在1到大约10的1之间打印。 - 如果我在
/*A*/
处设置一个断点,然后逐步执行流,它将仅输出1。 - 如果我在
/*B*/
处设置了一个断点,则只有一个线程会碰到该断点,并且在恢复时(整个程序)将仅打印一个1。 在所有情况下,都不会打印“无死锁”。
我首先想到的是,我正在调用的函数中的同步块是线程锁定的,但是,使用上面的测试代码,这是可以排除的。
我的第二个想法是其他地方正在执行使用全局forkjoinpool的操作。情况并非如此,但以防万一我在自定义的forkjoinpool中运行了代码,结果是什么都没有被打印出来,并且forkjoinpool中的任何断点(在执行list#parallelstream之前)都没有被击中。
我最后的猜测是它是由在通过static{}
块调用的方法中运行引起的。如果在static{}
块中运行此代码是原因,为什么会这样?