首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >引用类型的易失性--它是否总是避免因JMM而发布引用问题?

引用类型的易失性--它是否总是避免因JMM而发布引用问题?
EN

Stack Overflow用户
提问于 2012-11-14 00:08:07
回答 6查看 2.3K关注 0票数 7

假设这个类:

代码语言:javascript
复制
public class AmIThreadSafe {

    private int a;
    private int b;

    AmIThreadSafe(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

假设实例对该类的引用(声明为volatile)一旦this(引用)转义,某些线程(导致争用条件)即可访问:

代码语言:javascript
复制
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);

在这里,我确信分配instance引用的事实发生在线程读取之前。

但是AmIThreadSafe's字段呢?

外部volatile关键字是否也意味着与ab字段有关的happens-before关系?或者,是否有可能因为在构造函数期间可能出现语句重新排序而导致任何线程看到陈旧的值(在本例中是自int以来的默认值)?

换句话说,我应该声明ab finalvolatile,以防止在JMM中出现任何意外,还是仅仅在实例的引用上指示volatile

下面的文章通过其示例证实,在我的示例中,ab不受阻止永久a关系的JMM优化的保护。

http://jeremymanson.blogspot.fr/2008/11/what-volatile-means-in-java.html

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-11-14 00:27:16

instance声明为volatile并不表示它的字段为volatile,但是如果我正确理解了您的问题,那么-是的,在您的情况下就足够了。

规范第17.4.5节

  • 在一个线程中发生volatile写入-在其他线程中读取任何后续的volatile之前。
  • 相同线程中的语句会发生在您所期望的关系之前。
  • 在人际关系发生之前就会发生。

因此,如果一个线程认为instance已经初始化,那么instance的初始化就在它之前发生,而instance字段的初始化发生在此之前,所以线程会认为instance的字段已经初始化了。

票数 4
EN

Stack Overflow用户

发布于 2012-11-14 00:11:21

,不,,这还不足以使它不稳定。但是,线程安全取决于使用。例如,如果另一个线程正在修改这些值,这仍然会产生意想不到的结果。

为简单起见,假设public变量

代码语言:javascript
复制
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);
if (instance.x == 0) {
   // instance.x might have changed between checking and assigning
   instance.x = instance.x + 1;
}

volatile只适用于变量(例如,xy并不会因为instance的存在而自动成为volatile )。这在JLS 8.3.1.4中应该是清楚的。

票数 4
EN

Stack Overflow用户

发布于 2012-11-14 00:14:01

在您的情况下,volatile只适用于AmlThreadSafe的引用。您仍然必须使实例变量(ab)成为volatile,或者在synchronized块中访问它们。否则,您可能会得到陈旧的数据。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13371066

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档