我们经常使用volatile
来确保每个线程都可以看到条件变量。
到目前为止,我在代码中看到volatile
字段都是primitive type
。
object
字段是否存在此问题?例如:
class a {
public String str;
public List list;
}
如果有一些线程会访问str和list,我必须添加'volatile'吗?
我想对Object
的每次访问都会直接来自Heap
,而Object
不会像原始类型一样进行缓存。
是吗?
答案 0 :(得分:28)
您必须区分对象引用和实际对象。
对于参考,您的字段修饰符是相关的。当您将引用更改为其他对象(即引用不同的String)时,其他Thread可能不会注意到该更改。如果您想强制实施可见性,则必须使用final
或volatile
。
堆上的实际对象不受字段修饰符的影响。相反,您如何看待此对象的每个字段由其自己的字段修饰符根据相同的规则确定(是volatile
还是final
?如果不是,则不会强制执行并发线程的可见性)
答案是:是的,您必须添加volatile
或final
。不过,从风格上来说,让场地最终会更好。它具有与Thread相同的效果,但也是一个更强的语句:此字段无法更改 - 这就是为什么它可以被JVM无忧缓存的原因。出于同样的原因,与volatile
相比,它带来了一点性能优势,Java不需要关心该字段是否再次发生变化而且不需要增加开销。
答案 1 :(得分:2)
添加volatile keyword
告诉编译器它绑定到change
。以便所有线程重新确认他们的local cached copy
与原始线程相同,如果有更改则更新它。你通常用Primitives找到它,因为通常原始值会被不同的线程递增或递减。但是对象,特别是List从来都不会改变
对象的引用。如果要将不同的对象分配给同一个变量,那么在运行时,您可以执行..