当前位置: 首页 > 面试题库 >

易失性:为什么阻止编译器重新排序代码

郑俊彦
2023-03-14
问题内容

据我所知,在Java中,volatile变量使线程直接对主CPU进行读/写操作(而不是在每个线程的缓存中),因此使其更改对其他线程可见。

我不知道的是:因此,为什么这项工作(易失性)可以阻止编译器/ CPU对代码的重新排序语句。

谢谢 :)


问题答案:

这是一个很好的示例,说明了禁止重新排序的目的是要解决的问题(从此处获取):

class VolatileExample {
    int x = 0;
    volatile boolean v = false;
    public void writer() {
        x = 42;
        v = true;
    }
    public void reader() {
        if (v == true) {
            //uses x - guaranteed to see 42.
        }
    }
}

在此示例中,v为易失性,但x不是。如果作者和阅读者同时执行并且读者看到v设置为truex则保证为42。在此之前的Java-5,编译器可以自由地重新排序的写入xv,所以你可以看到x在零点
以后 你见过v设置为true。这令人困惑,并导致细微的错误。Java-5内存模型通过使易失性写入几乎等同于同步来解决了此问题。



 类似资料:
  • a)为什么除了“00”之外还有其他输出? b)如何修改代码以便始终打印“00”。 对于a)我的回答是:在没有任何volatile/同步构造的情况下,编译器可以重新排序一些指令。特别是“this.initialint=val;”和“this.flag=true;”可以切换,这样就可以发生这种情况:线程都启动了,t1充电在前面。给定重新排序的指令,它首先设置flag=true。在它到达“this.in

  • 我决定要对一个特定的函数进行基准测试,所以我天真地编写了这样的代码: 一位同事指出,我应该将和变量声明为,以避免代码重新排序。例如,他建议优化器可以像这样有效地重新排序代码: 起初,我怀疑这种极端的重新排序是允许的,但经过一些研究和实验,我知道是允许的。 但volatile感觉不是正确的解决方案;volatile真的只是用于内存映射I/O吗? 然而,我添加了< code>volatile,发现不仅

  • 对易失性字段的写和读分别防止了在易失性字段之前和之后的读/写的重新排序。在写到易失性变量之前的变量读/写不能被重新排序为在它之后发生,在从易失性变量读到之后的读/写不能被重新排序为在它之前发生。但是这种禁止的范围是什么呢?正如我所理解的,volatile变量只能在使用它的块内防止重新排序,对吗? 为了清楚起见,让我举一个具体的例子。假设我们有这样的代码: 让我再举一个具体的例子来说明范围以澄清事情

  • 变量res的值应等于3。但是当我打开优化时,编译器错误地重新排列了指令,并且res包含一些垃圾。一些可能的重新排序示例: 这是编译器中的错误吗?还是不允许像这样访问结构数据成员? 编辑: 我刚刚意识到之前的代码实际上有效,抱歉。但这不起作用: 当编译时不知道变量i时,编译器会错误地重新排序指令。

  • 问题内容: 因此,我刚刚意识到反编译Java代码是多么容易。我一直在网上搜索,但似乎无法弄清楚 为什么 这么容易。每次我在Google上搜索“为什么要反编译文件?”之类的信息时,或“为什么Java这么容易反编译”,我所得到的只是指向可以轻松反编译我的代码的软件的链接。因此,我向您介绍StackOverflow:为什么Java可以转换回容易阅读的源代码,而C ++和其他语言对反编译不是很友好? 谢谢

  • 我对下面的代码段有一个问题。结果可能有一个结果[0,1,0](这是用JCStress执行的测试)。那么这是怎么发生的呢?我认为数据写入(data=1)应该在Actor2(guard2=1)中写入到guard2之前执行。我说得对吗?我问,因为很多时候我读到挥发物周围的说明没有重新排序。此外,根据这一点:http://tutorials.jenkov.com/java-concurrency/vola