gpt4 book ai didi

Java 编译器重新排序

转载 作者:搜寻专家 更新时间:2023-11-01 01:51:11 28 4
gpt4 key购买 nike

今天看了java面试题,看了这道题:问题:考虑以下 Java 代码片段,它正在初始化两个变量并且都不是 volatile 的,并且两个线程 T1 和 T2 正在修改这些值,如下所示,两者都不是同步的

int x = 0;
boolean bExit = false;

Thread 1 (not synchronized)
x = 1;
bExit = true;

Thread 2 (not synchronized)
if (bExit == true)
System.out.println("x=" + x);

现在告诉我们,线程 2 是否可以打印“x=0”?

所以,答案是"is"。在解释中有“因为没有对编译器的任何指令,例如同步或 volatile ,bExit=true 可能在编译器重新排序中出现在 x=1 之前。”在那之前我不知道编译器可以在它之后的另一行之前执行一行。

为什么要重新排序?如果我从不同的线程向控制台打印一些东西怎么办——应该先打印的行将在应该先打印的行之后打印(如果它们是从同一个线程打印的)?这对我来说很奇怪(也许是因为我第一次看到这个重新排序的东西)。有人可以解释一下吗?

最佳答案

如果 JIT 编译器* 不会根据 Java 标准更改结果,则它可以更改执行顺序。切换

x = 1;
bExit = true;

bExit = true;
x = 1;

不会改变结果,因为没有同步,即。根据标准,执行此操作时不应由另一个线程读取这些变量,并且这些语句都不需要另一个变量。 (在现代 CPU 上,这两个命令实际上将同时执行,这当然意味着未指定哪个将首先更改。)

不仅重新排序会导致这种行为。可能发生 bExit 可以在一个内存页中而 x 在另一个内存页中,如果应用程序运行在多处理器(或多核)系统上,那么没有同步,可能会发生带有 bExit 的内存页将在带有 x 的内存页之前提交(并且对它的更改将在所有其他内核中可见)。

*编辑:Java 编译器(将 .java 编译成 .class)无法更改线程内执行顺序,但 JIT 编译器(将 .class 编译成二进制代码)可以。但是,如果 Java 编译器认为它们是多余的,则可以省略某些语句,例如。

x = 1;
bExit = true;
x = 2;

可以优化掉 x = 1;

关于Java 编译器重新排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31015169/

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