将对象声明为volatile

时间:2013-03-18 21:45:05

标签: java multithreading volatile

如果在Java中将成员变量声明为volatile,这是否意味着所有对象的数据都存储在易失性存储器中,或者对象的引用存储在易失性存储器中?

例如,如果我有以下类:

class C{
   int i = 0;
   char c = 'c';
}

如果我按如下方式声明它的实例:

private volatile C obj;

是否将obj的引用存储在易失性内存中,或obj的数据(obj.iobj.c)存储在volatile内存中?

是否使obj.cobj.i线程安全?

4 个答案:

答案 0 :(得分:16)

是的,只有对象引用被JVM认为是易失性的,而不是将驻留在堆上的对象数据本身。如果您要求堆上对象的成员变量是volatile,您当然可以将关键字应用于这些原语

class C {
   volatile int i = 0;
   volatile char c = 'c';
}

Re:你是否使变量线程安全的问题取决于你如何使用变量。正如@gerrytan从Oracle文档中指出的那样,volatile关键字确实有助于读取或写入是原子的,但是请注意,这与它始终是线程安全的不同。请考虑以下代码......

if(obj != null) {
    obj.doSomething();
}

执行空检查的线程仍然可能在执行obj.doSomething()之前被中断,而另一个线程设置obj = null。这里需要一些其他机制,例如synchronized块。

答案 1 :(得分:3)

private volatile C obj;

这只会使obj不稳定。

  

它是否使obj.c和obj.i线程安全?

没有。为了使它们具有线程安全性,您必须同步对它们的访问。

答案 2 :(得分:3)

这只会使对象引用 volatile 。 为了使obj.i和obj.c也 volatile ,你必须明确地将它们变为 volatile

class C{
   volatile int i = 0;
   volatile char c = 'c';
}

答案 3 :(得分:1)

如果在Java中将成员变量声明为volatile,这是否意味着所有对象的数据都存储在易失性存储器中,或者对象的引用存储在易失性存储器中?

当我们将对象声明为volatile时,我们实际上告诉底层处理器如何使用Volatile Object。每次CPU指令读取时都会从Heap调用一个新的副本,并且每次在对象上执行写操作它被保存到堆中并可供其他线程使用。因此,处理器不会从缓存旧值中选择,也不会写入缓存并等待缓存写回堆。

是否使obj.c和obj.i线程安全? 不。它只是保证当你阅读对象时你总是会有一个新的副本。当你使用基于可变量值的变量和处理逻辑时,很可能有人可能已经改变了背景中的值,当你更新它,您正在更新不同的值。