在Java中对volatile对象进行非易失性引用的行为
来自C / C ++,我对Java中的volatile对象行为有点困惑。
我知道Java中的volatile有两个属性:
- 不会将对象带入缓存,始终将其保存在主内存中。
- 保证“发生在之前”
但是我不确定如果我对对象进行新的非易失性引用会发生什么。 例如,
class Example { private volatile Book b = null; public init() { b = new Book(...); } public use() { Book local = b; local.read(); } }
AFAIK,volatile表示b引用的“book对象”应该在主内存中。 编译器可能在内部实现引用作为指针,因此b指针可能位于缓存中。 根据我的理解,volatile是对象的限定符,而不是引用/指针。
问题是:在use方法中,本地引用不是volatile。 这个“本地”引用是否会将基础Book对象从主内存带入缓存,从根本上使对象不“易变”?
没有“易失物体”这样的东西,也没有“永远保持在主存储器中”的保证。
引用类型保证的所有volatile
变量都是在对该变量的写入与后续读取同一变量之间存在先发生关系。
由于发生之前 –关系是可传递的,它们适用于您的示例代码,即对于b = new Book(...)
,对Book
实例所做的所有修改都是在将引用写入b
之前提交的,因此对于Book local = b; local.read();
Book local = b; local.read();
read()
保证在写入引用之前看到其他线程所做的所有这些修改。
这并不意味着Book
实例的内存很特殊。 例如, 在将引用写入b
之后对实例进行的修改可能对其他线程可见或者可能不可见,并且其他线程可能仅感知其中的一些或者看到它们好像以不同的顺序进行。
因此,获取对象引用的方式无关紧要,重要的是是在通过b
发布对该对象的引用之前还是之后进行更改。 同样,只要在通过读取b
获取引用后执行此操作,就无论如何执行对象的读取访问都无关紧要。
使用local.read();
你通过局部变量local
和read()
访问对象,虽然this
可以访问相同的引用,但重要的是你在读取对象的状态之前通过读取b
获取引用。
volatile
是关于引用,而不是对象。
它保证在另一个线程设置了b
值之后读取变量b
任何线程将获得由另一个线程分配给b
的值,而不是某些缓存值。