Java 将对象声明为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

如果在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
线程安全

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与其说是原子性,还不如说是可见性;类是否是线程安全的。