Java 将对象声明为volatile
如果在Java中将成员变量声明为volatile,这是否意味着所有对象的数据都存储在volatile内存中,或者对对象的引用存储在volatile内存中 例如,如果我有以下课程:Java 将对象声明为volatile,java,multithreading,volatile,Java,Multithreading,Volatile,如果在Java中将成员变量声明为volatile,这是否意味着所有对象的数据都存储在volatile内存中,或者对对象的引用存储在volatile内存中 例如,如果我有以下课程: class C{ int i = 0; char c = 'c'; } 如果我声明它的一个实例如下: private volatile C obj; 它是否将对obj的引用存储在易失性存储器中,或者将obj的数据(obj.i和obj.c)存储在易失性存储器中 它是否使obj.c和obj.i线程安全 pr
class C{
int i = 0;
char c = 'c';
}
如果我声明它的一个实例如下:
private volatile C obj;
它是否将对obj
的引用存储在易失性存储器中,或者将obj
的数据(obj.i
和obj.c
)存储在易失性
存储器中
它是否使obj.c
和obj.i
线程安全
private volatile C obj;
这只会使obj
不稳定
它是否使obj.c和obj.i线程安全
private volatile C obj;
否。要使它们线程安全,必须同步对它们的访问。这只会使对象引用不稳定。 为了使obj.i和obj.c也具有易变性,必须显式地使它们具有易变性
class C{
volatile int i = 0;
volatile char c = 'c';
}
是的,JVM只会认为对象引用是易变的,而不会认为对象数据本身是驻留在堆上的。如果您要求堆上对象的成员变量是可变的,那么您当然可以将关键字应用于这些原语
class C {
volatile int i = 0;
volatile char c = 'c';
}
Re:这是否使变量线程安全取决于您如何使用变量。正如@gerrytan在Oracle文档中指出的,volatile关键字确实有助于将读或写变为原子,但是请注意,这与始终是线程安全的不同。考虑下面的代码…
if(obj != null) {
obj.doSomething();
}
执行空检查的线程仍然可能在执行
obj.doSomething()
之前被中断,另一个线程设置obj=null
。这里还需要一些其他机制,例如同步的块。如果在Java中将成员变量声明为volatile,这是否意味着所有对象的数据都存储在volatile内存中,或者对对象的引用存储在volatile内存中
当我们将对象声明为volatile时,实际上是在告诉底层处理器如何处理volatile对象。每次CPU指令读取该对象时,都会从堆中调用一个新副本,每次对该对象进行写入时,它都会保存到堆中,并可供其他线程使用。因此,处理器不会从缓存中拾取旧值,也不会写入缓存,而是等待将缓存写回堆
它是否使obj.c和obj.i线程安全?
不。它只是保证你在阅读对象时总是有一个新的副本。而且很有可能当你使用变量和基于变量值的处理逻辑时,有人可能在后台更改了值,当你更新它时,您正在更新一个不同的值。JavaSE6教程没有将volatile
关键字指定为在易失性内存中存储对象,但它确保读取和写入是原子的。所有变量都存储在易失性存储器(即RAM)中,而与volatile
修饰符无关@gerrytan volatile与其说是原子性,还不如说是可见性;类是否是线程安全的。