gpt4 book ai didi

java - 为什么静态初始化器中带有 lambda 的并行流会导致死锁?

转载 作者:太空宇宙 更新时间:2023-11-04 09:17:33 24 4
gpt4 key购买 nike

我遇到了一个奇怪的情况,在静态初始化器中使用带有 lambda 的并行流似乎需要很长时间,而且没有 CPU 利用率。代码如下:

class Deadlock {
static {
IntStream.range(0, 10000).parallel().map(i -> i).count();
System.out.println("done");
}
public static void main(final String[] args) {}
}

这似乎是此行为的最小重现测试用例。如果我:

  • 将该 block 放在主方法中而不是静态初始化程序中,
  • 删除并行化,或
  • 删除 lambda,

代码立即完成。谁能解释这种行为?这是一个错误还是有意为之?

我使用的是 OpenJDK 版本 1.8.0_66-internal。

最佳答案

我发现了一个非常相似的案例 ( JDK-8143380 ) 的错误报告,该报告已被 Stuart Marks 关闭为“不是问题”:

This is a class initialization deadlock. The test program's main thread executes the class static initializer, which sets the initialization in-progress flag for the class; this flag remains set until the static initializer completes. The static initializer executes a parallel stream, which causes lambda expressions to be evaluated in other threads. Those threads block waiting for the class to complete initialization. However, the main thread is blocked waiting for the parallel tasks to complete, resulting in deadlock.

The test program should be changed to move the parallel stream logic outside of the class static initializer. Closing as Not an Issue.

<小时/>

我找到了另一个错误报告( JDK-8136753 ),也被 Stuart Marks 关闭为“不是问题”:

This is a deadlock that is occurring because the Fruit enum's static initializer is interacting badly with class initialization.

See the Java Language Specification, section 12.4.2 for details on class initialization.

http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.2

Briefly, what's happening is as follows.

  1. The main thread references the Fruit class and starts the initialization process. This sets the initialization in-progress flag and runs the static initializer on the main thread.
  2. The static initializer runs some code in another thread and waits for it to finish. This example uses parallel streams, but this has nothing to do with streams per se. Executing code in another thread by any means, and waiting for that code to finish, will have the same effect.
  3. The code in the other thread references the Fruit class, which checks the initialization in-progress flag. This causes the other thread to block until the flag is cleared. (See step 2 of JLS 12.4.2.)
  4. The main thread is blocked waiting for the other thread to terminate, so the static initializer never completes. Since the initialization in-progress flag isn't cleared until after the static initializer completes, the threads are deadlocked.

To avoid this problem, make sure that a class's static initialization completes quickly, without causing other threads to execute code that requires this class to have completed initialization.

Closing as Not an Issue.

<小时/>

请注意FindBugs has an open issue for adding a warning对于这种情况。

关于java - 为什么静态初始化器中带有 lambda 的并行流会导致死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58789834/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com