首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实时编译器如何优化Java并行流?

实时编译器如何优化Java并行流?
EN

Stack Overflow用户
提问于 2018-02-08 14:55:30
回答 1查看 646关注 0票数 5

不久前,一个有趣的question被问到:

代码语言:javascript
复制
Can (a == 1 && a == 2 && a == 3) evaluate to true in Java?

我决定证明使用Java8StreamAPI(准确地说是并行流)是可能的。下面是在非常罕见的情况下工作的代码:

代码语言:javascript
复制
class Race {
    private static int a;

    public static void main(String[] args) {
        IntStream.range(0, 100_000).parallel().forEach(i -> {
            a = 1;
            a = 2;
            a = 3;
            testValue();
        });
    }

    private static void testValue() {
        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        }
    }
}

然后我想,也许是因为潜在的JIT编译器优化?因此,我尝试使用以下VM选项运行代码:

代码语言:javascript
复制
-Djava.compiler=NONE

我禁用了JIT,成功案例的数量也大大增加了!

如何在时间内编译器优化并行流,以便优化可能影响上述代码执行?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-08 21:54:24

溪流不重要。只有两个简单的线程(如this answer中的线程)就可以观察到同样的效果。

a不是volatile时,JIT编译器可以进行优化(实际上它是这样做的!)连续作业。

代码语言:javascript
复制
    a = 1;
    a = 2;
    a = 3;

被转换成

代码语言:javascript
复制
    a = 3;

此外,JIT编译器还将if (a == 1 && a == 2 && a == 3)优化为if (false),然后以死代码的形式安全地删除整个testValue()调用。

让我们看看为lambda生成的程序集。

要打印编译后的代码,我使用-XX:CompileCommand=print,Race::lambda$main$0

代码语言:javascript
复制
  # {method} {0x000000001e142de0} 'lambda$main$0' '(I)V' in 'Race'
  # parm0:    rdx       = int
  #           [sp+0x20]  (sp of caller)
  0x00000000052eb740: sub     rsp,18h
  0x00000000052eb747: mov     qword ptr [rsp+10h],rbp  ;*synchronization entry
                                                ; - Race::lambda$main$0@-1 (line 8)

  0x00000000052eb74c: mov     r10,76b8940c0h    ;   {oop(a 'java/lang/Class' = 'Race')}
  0x00000000052eb756: mov     dword ptr [r10+68h],3h  ;*putstatic a
                                                ; - Race::lambda$main$0@9 (line 10)

  0x00000000052eb75e: add     rsp,10h
  0x00000000052eb762: pop     rbp
  0x00000000052eb763: test    dword ptr [3470000h],eax
                                                ;   {poll_return}
  0x00000000052eb769: ret

除了方法序言和eplilogue,只有一条指令存储值3:

代码语言:javascript
复制
  mov     dword ptr [r10+68h],3h  ;*putstatic a

因此,一旦编译了该方法,System.out.println就永远不会发生。当您看到“成功”时,这些罕见的情况发生在解释过程中,当代码尚未被JIT编译时。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48688363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档