最终与波动的保证书,以安全发布对象

时间:2013-02-09 17:03:24

标签: java java-memory-model

从Java并发实践中的书:

  

安全地发布对象,两者都是   引用对象和   必须使对象的状态可见   其他线程同时。一个   正确构造的对象可以   安全发布者:

     
      
  • 从静态初始化程序初始化对象引用

  •   
  • 将对它的引用存储到易失性字段或AtomicReference

  •   
  • 将对它的引用存储到正确构造的最终字段中   对象

  •   
  • 将对它的引用存储到由正确保护的字段中   锁。

  •   

我的问题是:

  1. 第2点和第3点有什么不同?我对volatile方法和final方法在安全发布对象方面的区别感兴趣。
  2. 第3点中正确构造的对象的最终字段是什么意思?在开始项目符号之前,作者已经提到他们正在谈论一个正确构造的对象(我假设它不会让this引用转义)。但他们为什么再次提到正确构造的物体?

2 个答案:

答案 0 :(得分:12)

  

第2点和第3点有什么区别?

  • volatile基本上意味着对该字段的任何写入都将从其他线程中可见。因此,当您将字段声明为volatile:private volatile SomeType field;时,可以保证如果构造函数写入该字段:field = new SomeType();,那么随后尝试读取{{1}的其他线程将看到此分配}。
  • field具有非常相似的语义:您可以保证如果您有一个最终字段:final写入该字段(在声明或构造函数中):{{1}如果对象正确发布(例如,private final SomeType field;没有转义),则不会重新编码并且其他线程将可见。

显然,主要的不同之处在于,如果该字段是最终字段,则只能分配一次。

  

他在第3点中正确构造的物体的最终场是什么意思?

例如,如果让field = new SomeType();从构造函数中逃脱,最终语义提供的保证就会消失:观察线程可能会看到该字段的默认值(对象为null)。如果对象构造正确,则不会发生这种情况。


受挫的例子:

this

答案 1 :(得分:1)

发布volatilefinal的效果没有区别,只有final只能在构造函数中设置一次,因此您阅读的内容永远不会更改。

我相信一个正确构造的对象确实是你所指的,一个this引用没有逃避它的构造函数并且以安全的方式发布到它的线程的对象用于。