Java volatile语义,JMM保证

时间:2018-04-12 14:59:58

标签: java multithreading concurrency

请考虑以下代码段。

public class Visibility {

    private volatile SomeData data;

    public static class SomeData {

        private int number;

        public SomeData(int number) {
            this.number = number;
        }

        public int getNumber() {
            return number;
        }
    }

    public void initialize() {
        data = new SomeData(42);
    }

    public SomeData getData() {
        return data;
    }
}

如果number字段为final,则任何看到data引用的线程不是null(在称为initialize的其他线程之后)也保证会看到{{1} }字段值为number

我们对非最终领域有同样的保证吗? 换句话说,某些线程是否有可能观察到非null 42引用,data字段为number

提前致谢!

2 个答案:

答案 0 :(得分:2)

某些线程观察到非空数据引用可能,但数字字段为0。

请参阅volatile的doc

  

这意味着对volatile变量的更改始终可见   其他线程。更重要的是,它还意味着当线程读取时   volatile变量,它不仅看到了volatile的最新变化,   以及导致更改的代码的副作用

因此,当您获得非空data时,它必须已成功启动,number必须为非零。

答案 1 :(得分:1)

通常,是的,如果字段未以安全方式发布,则可以看到处于部分构造状态的字段。在您的问题的特定情况下,volatile关键字是一种令人满意的安全发布形式。根据{{​​3}}:

  

安全地发布对象,包括对象的引用和   必须同时使对象的状态对其他线程可见。   正确构造的对象可以通过以下方式安全地发布:

     
      
  • 从静态初始值设定项初始化对象引用。
  •   
  • 将对它的引用存储到volatile字段中。
  •   
  • 将对它的引用存储到最终字段中。
  •   
  • 将对它的引用存储到由(同步)锁定正确保护的字段中。
  •   

有关详细信息,请参阅以下内容: