我已阅读以下参考文献:
http://tutorials.jenkov.com/java-concurrency/volatile.html
https://www.geeksforgeeks.org/volatile-keyword-in-java/
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
但是,我仍然不清楚在以下情况下的预期行为:
我不清楚的部分是。我是否仍然需要volatile以确保对下一个线程执行可见在前一个线程中所做的更改。
就像Java Flash线程在每次执行后将本地缓存缓存到内存一样吗?
该线程是否在每次执行前重新加载本地缓存?
它总是抱怨有没有引用的代码部分。因此,我必须这样做。请帮忙解决。
答案 0 :(得分:1)
Java内存模型设计可以回答您的问题: 在Java内存模型中,易失性字段在写入存储对象后插入存储屏障,在读取存储对象前插入加载屏障。合格的类的最终字段在初始化后插入了存储屏障,以确保在对对象的引用可用时构造函数完成后,这些字段就可见。
请参见https://dzone.com/articles/memory-barriersfences
换句话说:当线程尝试从易失性变量中读取时,JMM会强制拥有此内存区域的所有CPU从本地CPU的高速缓存写回内存。然后,如有必要,CPU会将其值加载到本地缓存中。
我不清楚的部分是。我是否仍然需要volatile以确保对下一个线程执行可见在前一个线程中所做的更改。
是,不是。 Volatile关键字仅用于使变量的值对其他线程可见。但是,如果此时仅需要一个线程读写,则需要同步。如果您只需要提供可见性= volatile关键字就足够了。
如果您不使用volatile关键字并通过线程共享值,则它可能不是最新的,甚至已损坏。对于LONG类型的Java,按32位执行2次写操作,它们不是原子的。假设另一个线程可以读取两次写入之间的值。
答案 1 :(得分:1)
线程是否按顺序并行运行无关紧要,如果不使用volatile关键字,则无法保证可见性。这意味着不能保证另一个线程会看到最新的副本,因为该线程可以从寄存器中读取值。