"volatile"在Java中意味着什么?

jni*_*ddy 26 java volatile java-memory-model

我们volatile在其中一个项目中使用它来维护不同线程访问的变量的相同副本.我的问题是,它是否是正常的使用volatile有static.编译器没有给出任何错误,但我不明白使用两者的原因.

ide*_*ide 19

如果没有阅读内存模型规范,我建议您阅读http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html.它是由JMM的一位作者撰写的,应该回答你的问题.根据before-before子句考虑内存读写也很有帮助; JMM for Java 5以后添加了语义之前发生的事件volatile.

具体来说,当您从一个线程读取一个volatile变量时,所有写入(包括从其他线程写入该volatile变量)的写入现在对该一个线程可见.如果您有时间,可以通过Google技术讲座进一步讨论该主题:https://code.google.com/edu/languages/#_java_memmodel.

而且,是的,你可以用static用volatile.他们做不同的事情.

  • "当一个字段被声明为volatile时,编译器和运行时会注意到这个变量是共享的,并且对它的操作不应该与其他内存操作重新排序.易失性变量不会缓存在寄存器或缓存中,它们被隐藏在其他处理器,因此读取volatile变量总是返回任何线程的最新写入." 布洛赫,约书亚; 格茨,布莱恩; 皮尔斯,蒂姆; 鲍比尔,约瑟夫; 福尔摩斯,大卫; Lea,Doug(2006-05-09).Java Concurrency in Practice(Kindle Locations 1194-1197).培生教育(美国).Kindle版. (3认同)
  • 易失性变量的可见性影响超出了易失性变量本身的值。当线程 A 写入易失性变量并且随后线程 B 读取同一变量时,在写入易失性变量之前对 A 可见的所有变量的值在读取易失性变量后对 B 来说都可见。布洛赫,约书亚;戈茨,布莱恩;蒂姆·佩尔斯;鲍比尔,约瑟夫;福尔摩斯,大卫;利亚·道格 (2006-05-09)。Java 并发实践(Kindle 位置 1202-1205)。培生教育(美国)。Kindle版。 (2认同)

Pau*_*her 11

在Java中,volatile具有与C中类似的一般含义.Java Memory Model(参见ide的答案中的优秀链接)允许线程同时"看到"标记为非易失性的变量的不同值.例如:

线程a:

n = 1;
// wait...
n = 2;
Run Code Online (Sandbox Code Playgroud)

线程B和C:

while (true) {
    System.out.println(name + ": " + n);
}
Run Code Online (Sandbox Code Playgroud)

允许这个输出发生(注意你不能保证在B和C之间严格交替,我只是想在这里显示B和C的"转换"):

C: 1
B: 1
C: 2
B: 1
C: 2
B: 2
Run Code Online (Sandbox Code Playgroud)

这与锁定完全分开println; 线程B 允许看到n为1 C发现后,即使退出,它的2.有各种各样的很好的理由这一点,我不能假装要充分了解,许多关于速度,以及一些关于安全性.

如果它是不稳定的,你可以保证(除了println锁定之外,我暂时会忽略它),B和C一旦发送就会"同时"看到B的新值.

您可以使用volatile,static因为它们会影响不同的事物. volatile导致更改变量以"复制"到在使用该变量之前使用该变量的所有线程,同时static在使用该变量的所有类之间共享单个变量.(对于刚接触Java的线程的人来说,这可能会让人感到困惑,因为每一个都Thread恰好被实现为class.)


小智 8

volatile 表示变量在运行时更改,并且编译器不应出于任何原因缓存其值.

这在线程之间共享变量时只是一个问题,您不希望线程使用过时数据,因此编译器永远不应该缓存volatile变量引用的值.


小智 6

考虑这样一个场景:两个线程(Thread1 和 Thread2)正在访问值为 1 的同一变量“mObject”。

当 Thread1 运行时,它不希望其他线程修改变量“mObject”。在这种情况下,Thread1 缓存了值为 1 的变量“mObject”。

如果 Thread2 将“mObject”的值修改为 2,Thread1 仍然会将 mObject 值引用为 1,因为它进行了缓存。为了避免这种缓存,我们应该将变量声明为

私有易失性 int mObject;

在这种情况下,Thread1 将获取 mObject 的更新值