2013-03-18 101 views
5

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

例如,如果我有下面的类:

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

如果我声明它的一个实例如下:

private volatile C obj; 

这是否存储参考到obj在易失性存储器,或obj的数据(obj.iobj.cvolatile内存?

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

+2

Java SE 6教程未指定'volatile'关键字作为存储对象在易失性内存中,但它确保读取和写入是原子性的。 http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html – gerrytan 2013-03-18 21:51:55

+0

所有变量都存储在易失性存储器(即RAM)中,而不考虑volatile属性。 http://en.wikipedia.org/wiki/Volatile_memory – 2013-03-19 00:02:19

+0

@gerrytan挥发性不是关于原子性,而是关于可见性。 – assylias 2013-03-22 08:47:13

回答

8

是只有对象的引用将被认为是由JVM挥发而不是对象数据本身将驻留在堆上。如果您需要在堆中对象的成员变量挥发您可以在关键字的过程适用于那些原语

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

回复:您这是否使得可变线程安全的问题,取决于你如何使用变量。正如@gerrytan从Oracle文档中指出的那样,volatile关键字确实有助于读取或写入为原子,但要警告的是,这不总是线程安全的。请看下面的代码...

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

它仍然是可能的,执行空校验线程,被中断它执行obj.doSomething()之前,另一个线程设置obj = null。此处需要其他一些机制,例如​​块。

+0

伟大的答案:)谢谢! – user965369 2013-03-19 00:49:30

3
private volatile C obj; 

这将使只有obj易失性。

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

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

+1

这反映了一个类的_instances_不是线程安全的一般原则; _classes_线程安全或不安全。 – 2013-03-18 22:01:20

2

这只会使对象引用不稳定。 为了使obj.i和obj.c也挥发性你必须让他们挥发性明确

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

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

当我们将对象声明为volatile时,我们实际上告诉底层处理器如何使用易失性对象。每次通过CPU指令读取时,都会从堆中调用新副本,并且每次在对象将其保存到堆并可供其他线程使用。因此,处理器不会从缓存旧值中选取,也不会写入缓存并等待缓存写回堆。

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