gpt4 book ai didi

java - 你什么时候在 Java 中使用 volatile 关键字?

转载 作者:IT老高 更新时间:2023-10-28 11:38:30 25 4
gpt4 key购买 nike

我已阅读“When to use 'volatile' in Java?”,但我仍然感到困惑。我如何知道何时应该将变量标记为 volatile?如果我弄错了,要么在需要它的东西上省略 volatile,要么在不需要的东西上添加 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 的更改可能对主线程“可见”,也可能不“可见”。

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

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

编辑:
对此评论的回应:

Ok, but why can't we make todaysTemperature synchronized and create a synchronized getter for temperature?

您可以并且它会正常运行。 volatile 可以做的任何事情都可以用 synchronized 来完成,反之则不行。如果可以的话,您可能更喜欢 volatile 的原因有两个:

  1. 不易出现错误:这取决于上下文,但在许多情况下使用 volatile 不太容易出现并发错误,例如在持有锁时阻塞、死锁等。
  2. 更高性能:在大多数 JVM 实现中,volatile 可以具有显着更高的吞吐量和更好的延迟。然而,在大多数应用程序中,差异太小而无关紧要。

关于java - 你什么时候在 Java 中使用 volatile 关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3488703/

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