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

何时在Java中使用volatile关键字?

许茂才
2023-03-14
问题内容

我读过“ 何时在Java中使用’volatile’? ”,但我仍然感到困惑。我怎么知道何时应该将变量标记为volatile?如果我弄错了,或者在需要的东西上省略了挥发物,或者在不需要的东西上放置了挥发物,该怎么办?确定多线程代码中哪些变量应该是易变的,有什么经验法则?


问题答案:

当你想让一个多线程访问一个成员变量但不需要复合原子性(不确定这是否是正确的术语)时,基本上就可以使用它。

class BadExample {
    private volatile int counter;

    public void hit(){
        /* This operation is in fact two operations:
         * 1) int tmp = this.counter;
         * 2) this.counter = tmp + 1;
         * and is thus broken (counter becomes fewer
         * than the accurate amount).
         */
        counter++;
    }
}

上面的例子很糟糕,因为你需要复合原子。

class BadExampleFixed {
    private int counter;

    public synchronized void hit(){
        /*
         * Only one thread performs action (1), (2) at a time
         * "atomically", in the sense that other threads can not 
         * observe the intermediate state between (1) and (2).
         * Therefore, the counter will be accurate.
         */
        counter++;
    }
}

现在来看一个有效的例子:

 class GoodExample {
    private static volatile int temperature;

    //Called by some other thread than main
    public static void todaysTemperature(int temp){
        // This operation is a single operation, so you 
        // do not need compound atomicity
        temperature = temp;
    }

    public static void main(String[] args) throws Exception{
        while(true){
           Thread.sleep(2000);
           System.out.println("Today's temperature is "+temperature);
        }
    }
}

现在,为什么不能只使用private static int temperature?实际上,你可以(从某种意义上说,你的程序不会崩溃),但是temperature另一个线程所做的更改可能对主线程“可见”或不可见。

基本上,这意味着你的应用甚至有可能。Today's temperature is 0如果你不使用它,将永远写下去volatile(实际上,该值往往最终会变得可见。但是,你不应冒险在必要时不使用volatile,因为它可能导致讨厌的bug(由构造不完全的对象等引起)。 )。

如果将volatile关键字放在不需要的地方volatile,则不会影响代码的正确性(即行为不会改变)。在性能方面,这将取决于JVM的实现。从理论上讲,由于编译器无法进行重新排序优化,必须使CPU缓存无效等原因,性能可能会略有下降,但是编译器可以再次证明你的字段无法被多个线程访问并消除volatile关键字的影响完全并将其编译为相同的指令

编辑:
对此评论的答复:

好的,但是为什么我们不能使今天的温度同步并为温度创建同步的吸气剂?

你可以,它将正常运行。你可以使用任何volatile方法完成操作synchronized,反之亦然。volatile如果可以的话,你可能有两个原因:

  1. 更少的错误倾向:这取决于上下文,但是在许多情况下,使用volatile并发错误的可能性较小,例如在持有锁时阻塞,死锁等。
  2. 性能volatile更高:在大多数JVM实现中,可以具有更高的吞吐量和更好的延迟。但是,在大多数应用中,差异很小,无关紧要。


 类似资料:
  • 我知道关于volatile有很多问题,但我只是被讨论搞糊涂了:Java:volatile如何保证这段代码中“数据”的可见性? 我读过的每个网站都说可以在缓存中存储一个变量(使这个值对于其他线程不可见),我甚至发现了这个例子https://dzone.com/articles/java-volatile-keyword-0 所以我的第一个问题是:Java是否在缓存中存储变量值(在哪个缓存中?l1 l

  • 本文向大家介绍Java中的volatile关键字,包括了Java中的volatile关键字的使用技巧和注意事项,需要的朋友参考一下 volatile修饰符用于让JVM知道访问该变量的线程必须始终将其自身的变量私有副本与内存中的主副本合并。 访问易失性变量将同步所有在主存储器中缓存的变量副本。可变变量只能应用于对象类型或私有类型的实例变量。易失性对象引用可以为null。 示例

  • 问题内容: 从java4和java5开始使用时有什么区别? 与此相关的是 当非原子变量(长/双)被声明为volatile时,它们的读/写操作是原子的。 这对于Java4 还是 正确的, 或者 从Java5开始有效???? 问题答案: 人们回答了我回答第一部分的问题时提供了好的观点和参考。 具体到问题的第二部分,我在某个论坛上阅读过: volatile声明的long是原子的(也是Java 5之前的版

  • 问题内容: 今天的工作中,我遇到了volatileJava中的关键字。不太熟悉,我发现了以下解释: Java理论与实践:管理波动 鉴于该文章详细解释了所讨论的关键字,您是否曾经使用过它,或者是否曾经遇到过可以正确使用此关键字的情况? 问题答案: volatile具有内存可见性的语义。基本上,字段的值对所有读取器(尤其是其他线程)在写入操作完成后变为可见。没有,读者可能会看到一些未更新的值。 回答你

  • 本文向大家介绍解析java中volatile关键字,包括了解析java中volatile关键字的使用技巧和注意事项,需要的朋友参考一下 在java多线程编程中经常volatile,有时候这个关键字和synchronized 或者lock经常有人混淆,具体解析如下: 在多线程的环境中会存在成员变量可见性问题: java的每个线程都存在一个线程栈的内存空间,该内存空间保存了该线程运行时的变量信息,当线

  • 本文向大家介绍Java使用volatile关键字的注意事项,包括了Java使用volatile关键字的注意事项的使用技巧和注意事项,需要的朋友参考一下  Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量