今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。
鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?
今天工作时,我在Java中遇到了volatile关键字。不是很熟悉,我找到了这个解释。
鉴于那篇文章详细解释了所讨论的关键字,您曾经使用过它吗?或者您曾经看到过以正确方式使用该关键字的情况吗?
当前回答
…volatile修饰符保证任何读取字段的线程都能看到最近写入的值。——乔希·布洛赫 如果您正在考虑使用volatile,请仔细阅读java.util.concurrent包,它处理原子行为。 维基百科上关于单例模式的帖子显示了volatile的使用。
其他回答
是的,我经常使用它——它对多线程代码非常有用。你指的那篇文章很好。不过有两件重要的事情要记住:
You should only use volatile if you completely understand what it does and how it differs to synchronized. In many situations volatile appears, on the surface, to be a simpler more performant alternative to synchronized, when often a better understanding of volatile would make clear that synchronized is the only option that would work. volatile doesn't actually work in a lot of older JVMs, although synchronized does. I remember seeing a document that referenced the various levels of support in different JVMs but unfortunately I can't find it now. Definitely look into it if you're using Java pre 1.5 or if you don't have control over the JVMs that your program will be running on.
从oracle文档页,需要volatile变量来修复内存一致性问题:
使用易失性变量可以降低内存一致性错误的风险,因为对易失性变量的任何写入都会与该变量的后续读取建立happens-before关系。
这意味着对volatile变量的更改总是对其他线程可见。这也意味着当线程读取一个volatile变量时,它不仅看到了volatile的最新更改,还看到了导致更改的代码的副作用。
正如在Peter Parker的回答中解释的那样,在没有volatile修饰符的情况下,每个线程的堆栈都可能有自己的变量副本。通过将变量设置为volatile,可以修复内存一致性问题。
为了更好地理解,请查看jenkov教程页面。
看一下相关的SE问题,了解更多关于volatile的细节和使用volatile的用例:
Java中volatile和synchronized的区别
一个实际的用例:
你有很多线程,它们需要以特定的格式打印当前时间,例如:java.text.SimpleDateFormat("HH-mm-ss")。可以有一个类,它将当前时间转换为SimpleDateFormat,并每一秒更新一次变量。所有其他线程都可以使用这个易失性变量在日志文件中打印当前时间。
…volatile修饰符保证任何读取字段的线程都能看到最近写入的值。——乔希·布洛赫 如果您正在考虑使用volatile,请仔细阅读java.util.concurrent包,它处理原子行为。 维基百科上关于单例模式的帖子显示了volatile的使用。
在我看来,除了停止线程之外,使用volatile关键字的两个重要场景是:
Double-checked locking mechanism. Used often in Singleton design pattern. In this the singleton object needs to be declared volatile. Spurious Wakeups. Thread may sometimes wake up from wait call even if no notify call has been issued. This behavior is called spurious wakeup. This can be countered by using a conditional variable (boolean flag). Put the wait() call in a while loop as long as the flag is true. So if thread wakes up from wait call due to any reasons other than Notify/NotifyAll then it encounters flag is still true and hence calls wait again. Prior to calling notify set this flag to true. In this case the boolean flag is declared as volatile.
Volatile变量基本上用于主共享缓存线上的即时更新(刷新),以便立即将更改反映到所有工作线程。