我们在其中一个项目中使用volatile
来维护不同线程访问的变量的相同副本。我的问题是,volatile
与static
一起使用是否可以。编译器没有给出任何错误,但我不明白使用它们的原因。
答案 0 :(得分:18)
如果没有阅读内存模型规范,建议您阅读http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html。它是由JMM的一位作者撰写的,应该回答你的问题。根据{{3}}子句考虑内存读写也很有帮助; JMM for Java 5以后在语句之前添加了volatile
。
具体来说,当您从一个线程读取一个volatile变量时,所有写入(包括从其他线程写入该volatile变量)的写入现在对该一个线程可见。如果您有时间,可以通过Google技术讲座进一步讨论该主题:happens-before。
而且,是的,您可以将https://code.google.com/edu/languages/#_java_memmodel与volatile
一起使用。他们做了不同的事情。
答案 1 :(得分:11)
在Java中,volatile具有与C中类似的一般含义.Java Memory Model(参见ide的答案中的优秀链接)允许线程同时“看到”标记为非的变量的不同值易挥发。例如:
线程a:
n = 1;
// wait...
n = 2;
主题B和C:
while (true) {
System.out.println(name + ": " + n);
}
允许这个输出发生(注意你不能保证在B和C之间严格交替,我只是想在这里显示B和C的“转换”):
C: 1
B: 1
C: 2
B: 1
C: 2
B: 2
这与println
的锁定完全分开;线程B 允许看到n
为1,即使在C发现它是2之后。有很多很好的理由让我无法完全理解,很多与速度有关,有些与安全有关。
如果它是不稳定的,你可以保证(除了println
的锁定,我暂时会忽略它)B和C将“同时”同时“看到B的新值”因为它被发送。
您可以将volatile
与static
一起使用,因为它们会影响不同的事物。 volatile
导致更改变量“复制”到使用该变量的所有线程,而static
在所有类中共享一个变量< / em>使用该变量。 (对于刚接触Java的线程的人来说,这可能会让人感到困惑,因为每个Thread
恰好都被实现为class
。)
答案 2 :(得分:8)
volatile
表示变量在运行时更改,并且编译器不应出于任何原因缓存其值。
在线程之间共享变量时,这只是一个问题,您不希望线程使用过时数据,因此编译器永远不应该缓存volatile
变量引用的值。
答案 3 :(得分:2)
易失性用于许多不同的情况,其中多个线程需要访问同一个变量。许多没有进行多线程/并发编程的人不会接触到这一点。 Volatile确保始终从主存储器读取变量,而不是从缓存/寄存器版本读取。 Volatile本身并不是一个锁,只是因为所有线程一旦写入就会看到更改并不意味着您可以以原子方式进行比较和交换。 但是,此功能可以与其他功能一起使用,例如比较和交换,以构建线程安全的数据结构,而不需要用户使用java的重做&#34;等待通知语义。 / p>
您可以在此链接上获得更多信息 http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-java
答案 4 :(得分:2)
考虑一个场景,当两个线程(Thread1和Thread2)访问值为1的同一个变量'mObject'时。
当Thread1运行时,它不希望其他线程修改变量'mObject'。在这种情况下,Thread1缓存值为1的变量'mObject'。
如果Thread2将'mObject'的值修改为2,那么Thread1仍会将mObject值引用为1,因为它进行了缓存。 为了避免这种缓存,我们应该将变量声明为
private volatile int mObject;
在这个场景中,Thread1将获得mObject的更新值
答案 5 :(得分:0)
详细说明,但volatile关键字不仅用于内存可见性。在发布Java版本1.5
之前,volatile关键字声明,该字段将通过每次访问主内存进行读取并刷新写入来获取该对象的最新值。
在最新的Java版本中,volatile关键字表示两个非常重要的内容:
查看更多Java volatile示例。