假设这堂课:
public class AmIThreadSafe { private int a; private int b; AmIThreadSafe(int a,int b) { this.a = a; this.b = b; } }
假设实例对此类的引用(声明为volatile)可以被一些线程访问(导致竞争条件),只要这个(引用)转义:
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);
在这里,我确信分配实例引用的事实发生在线程读取之前.
但是AmIThreadSafe的领域呢?
外部volatile关键字是否也意味着关于a和b字段的事先关系?
或者由于在构造函数中重新排序的潜在语句,是否有可能最终得到任何线程看到陈旧值(在本例中为int以来的默认值为0)?
换句话说,我应该声明a和b final或volatile来防止JMM的任何意外,或者只是在实例的引用上指示volatile吗?
—————-更新的帖子 – 一个好的答案:————————— –
以下文章通过其样本证实,在我的情况下,a和b受到保护,不受JMM优化的影响,这些优化可以防止永久发生在之前的关系.
http://jeremymanson.blogspot.fr/2008/11/what-volatile-means-in-java.html
解决方法
将实例声明为volatile不会使其字段变得不稳定,但如果我正确地理解了您的问题,那么 – 是的,在您的情况下就足够了.
>一个线程中的易失性写入发生在另一个线程中的任何后续易失性读取之前.
>同一个线程中的语句具有您期望的之前发生的关系.
>在关系传递之前发生.
因此,如果一个线程将实例视为已初始化,则实例的初始化发生在它之前,并且实例的字段的初始化发生在此之前,因此线程将感知实例的字段已经初始化.