当前位置: 首页 > 知识库问答 >
问题:

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

巩阳秋
2023-03-14

我遇到了一个奇怪的情况,在静态初始化器中使用带有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) {}
}

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

    null

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

共有1个答案

姜业
2023-03-14

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

这是类初始化死锁。测试程序的主线程执行类静态初始化器,它为类设置初始化进行中标志;在静态初始值设定项完成之前,此标志将保持设置。静态初始值设定项执行一个并行流,导致lambda表达式在其他线程中求值。这些线程阻塞等待类完成初始化。但是,主线程在等待并行任务完成时被阻塞,导致死锁。

应该更改测试程序,将并行流逻辑移动到类静态初始值设定项之外。结束时不是一个问题。

有关类初始化的详细信息,请参见Java语言规范第12.4.2节。

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

简而言之,正在发生的事情如下所示。

    null

请注意,FindBugs有一个未解决的问题,可以为这种情况添加警告。

 类似资料:
  • 问题内容: 注意: 这是不是重复,请仔细阅读题目 сarefully报价: 真正的问题是为什么代码有时在不应该运行的情况下仍然有效。即使没有lambda,该问题也会重现。这使我认为可能存在JVM错误。 在http://codingdict.com/questions/122889的评论中,我试图找出原因,导致代码行为从一个起点到另一个起点有所不同,而该讨论的参与者为我提供了一个建议,以创建一个单独

  • 在使用Java并行流时,当一些并行操作在静态初始化器块内完成时,我遇到了死锁。 当并行处理流时,所有的工作(数字不按顺序显示): 但是,当使用处理流时,会出现死锁(我假设这与主线程和ForkJoinPool管理之间的交互有关): 但是当在一个单独的线程中生成流处理时,一切都很顺利: 如果能理解为什么在某些情况下会出现僵局,而在其他情况下却不会出现这种情况,我将不胜感激。这显然不仅仅是因为使用了静态

  • 初始化的区别是什么:1)int i=47;或2)int i;{i=47;在哪些情况下我们需要第一个或第二个?

  • 最近,当我在LeetCode上做一些练习时,我发现了一些绝妙的解决方案。它使用对象o引用数组,我猜可能是因为在Java,所有的东西都是Object。但当我尝试这种方法时,它出错了。所以我尝试了所有的方法来初始化数组,我想看看它们之间的区别,就像下面这样 只有o3会编译一个错误。我不知道是不是因为初始化的方式。我知道当我使用静态初始化时,它会先分配内存,当使用动态初始化时,它不会。它们之间的其他差异

  • 我使用初始化Spring bean中的类属性。现在我看到这个任务可以通过Java内置的静态和非静态初始化器来完成。如何使用而不能使用初始化器块?

  • 最近我在写一些复杂的基于RX的流程,发现它总是在特定情况下产生死锁。我花了几个小时才找出问题所在,似乎可以在这个简单的示例中重现: 此程序应打印以下值:11、21、22、31、32、33、。。。,通常,值可以表示为XY。每组X中的值的顺序可以是随机的,但组的顺序应该是升序。如果previous仍在计算,则不应发出新组(这是我的原始情况)。 问题是,如果您运行这段代码,您将只看到前几个元素的输出-我