Java 在其他指令/语句之前出现的指令/语句是否保证首先执行?
考虑Joshua Bloch的《Java并发实践》一书中的片段-Java 在其他指令/语句之前出现的指令/语句是否保证首先执行?,java,Java,考虑Joshua Bloch的《Java并发实践》一书中的片段- public class NoVisibility{ private static boolean ready; private static int number; private static class ReaderThread extends Thread{ public void run(){ while(!ready) T
public class NoVisibility{
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread{
public void run(){
while(!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args){
new ReaderThread().start();
number = 42; // Statement 1
ready = true; // Statement 2
}
}
对于JVM启动的main线程,是否保证将在语句2之前执行语句1
我完全理解ReaderThread可能无法看到上述两个静态变量的更新值。我不是在寻求解决办法。但是如果语句1在语句2之前执行,ReaderThread是否仍然可以看到ready的更新值,而不是number的更新值?这就是重新排序的一般含义吗
同一本书页面底部的一段话揭示了这一点- 不能保证在一个线程中执行操作 按照程序给出的顺序,只要不重新排序 即使重新排序很明显,也可以从该线程中检测到 到其他线程 这里有点混乱- 作者说。。。只要重新排序无法从该线程中检测到。。。同时,他说- -即使重新排序对其他线程是明显的(清晰可见)
如果在这种情况下,重新排序对其他线程是清晰可见的,那么他为什么同时说“只要重新排序在该线程内不可检测到”如果重新排序可见,则意味着它也可检测到。不是吗?一般来说,这是不能保证的。此外,不保证发生更新,因为其中一个字段中没有添加任何
volatile
。这将同步线程的缓存,并保证顺序
(我希望我是对的。)
澄清(我希望) 给定的场景并不太关注jvm处理的java字节码。通常情况下,编译器不会巧妙地按顺序重新排列或解释字节码。它是运行在具有本地线程缓存的线程中的实时编译代码,重复地保存公共变量 volatile标记的字段确保这些公共变量与所有线程同步。当然,只要结果正常,单个线程可以按任意顺序执行代码
y = ++x;
以下伪程序集的实际执行
1. move from @x to register1
2. increment register1
3. move from register1 to @x
4. move from register1 to @y
5. synchronize @x and @y
在不同的处理器上可能会有很大的不同。一个或两个变量可能缓存在线程内存中,或者需要写入far变量,或者不需要
当然,可以保证处理相同的线程时会给出正确的结果。没有人看到,顺序是不相关的:4可能比3早,或者由于记忆的原因比3快
如果3。四,。如果JIT编译被切换,同一线程将不会看到/检测到任何差异,但其他线程可能首先看到y中的更改。这是没有volatile的
这一切都是相当深奥的,太低级了。有人可能会想,它出现在语言规范中,就像byte
变量在内部存储在一个4字节的字中一样。它处理与实现相关的问题,比如缺少字节操作。当有人对这个主题感兴趣时,可以使用汇编程序,也许可以与C结合使用,并尝试一下这些东西。否则,请远离不安全的编程
“是”这些陈述是按照您的书面顺序执行的,对于您的第二个问题:您可以找到一个很好的例子。所以是的,这是可能的。“在线程中不可检测”意味着在当前代码中它是不可检测的。e、 g.类似于
foo=1;睡十分钟;foo=2
可能只是从一开始就设置foo=2,因为它在执行线程中是不可检测的(它不检查值),但是其他线程在十分钟结束之前会看到foo==2。。。。执行顺序有保证。确实-但仅在当前线程中,另一个线程可能“看到”不同的东西:。请不要写你不确定的答案about@specializtJIT编译器和CPU可以自由地对这些语句重新排序。没有什么可以阻止,你也不希望它。。。。只有在重新排序“产生与合法执行一致的结果”的情况下,才可以在同一个线程中进行重新排序,因此实际上这并不重要,重新排序本身就是一个实现细节,保证结果一致。@是的,对于不同的线程,当然,对于单个线程,重新排序是不相关的(谁会发现呢?)。正如你所评论的。我对你所引述的技术细节表示怀疑。我喜欢你的纠正意见,谢谢。也请回答问题。@JoopEggen:谢谢。如果你也能回答第二部分,那将非常有帮助。