相关疑难解决方法(0)

关于在对象的构造函数完成之前对对象的引用

你们每个人都知道JMM的这个特性,有时候对象的引用可以完成这个对象的构造函数之前获得值.

JLS7中,p.17.5 最后的字段语义我们也可以阅读:

final字段的使用模型很简单:final在该对象的构造函数中设置对象的字段; 并且在对象的构造函数完成之前,不要在另一个线程可以看到的地方写入对正在构造的对象的引用.如果遵循这一点,那么当另一个线程看到该对象时,该线程将始终看到该对象的final字段的正确构造版本.(1)

在JLS之后,接下来的示例演示了如何不保证非最终字段的初始化(1Example 17.5-1.1) (2):

class FinalFieldExample { 
    final int x; 
    int y; 

    static FinalFieldExample f;

    public FinalFieldExample() { 
        x = 3; 
        y = 4; 
    } 

    static void writer() { 
        f = new FinalFieldExample(); 
    } 

    static void reader() { 
       if (f != null) { 
           int i = f.x; // guaranteed to see 3 
           int j = f.y; // could …
Run Code Online (Sandbox Code Playgroud)

java concurrency multithreading final jls

13
推荐指数
1
解决办法
2061
查看次数

"最新"保证Java的最终字段的值是否延伸到间接引用?

Java语言规范定义了第17.5节中最终字段的语义:

最终字段的使用模型很简单.在该对象的构造函数中设置对象的最终字段.在对象的构造函数完成之前,不要在另一个线程可以看到的位置写入对正在构造的对象的引用.如果遵循此原因,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本.它还将看到那些最终字段引用的任何对象或数组的版本,这些字段至少与最终字段一样是最新的.

我的问题是 - '最新'保证是否扩展到嵌套数组和嵌套对象的内容?

简而言之:如果一个线程将可变对象图分配给对象中的最终字段,并且对象图永远不会更新,那么所有线程都可以通过最终字段安全地读取该对象图吗?

示例场景:

  1. 线程A构造一个ArrayLists的HashMap,然后在类'MyClass'的实例中将HashMap分配给final字段'myFinal'
  2. 线程B看到对MyClass实例的(非同步)引用并读取'myFinal',并访问和读取其中一个ArrayLists的内容

在这种情况下,线程B看到的ArrayList的成员是否保证至少与MyClass的构造函数完成时一样最新?

我正在寻找澄清Java内存模型和语言规范的语义,而不是像同步这样的替代解决方案.我的梦想答案是肯定或否定,并参考相关文字.

更新:

  • 我对Java 1.5及更高版本的语义感兴趣,即通过JSR 133引入更新的Java内存模型.此更新中引入了最新字段的"最新"保证.

java memory concurrency synchronization final

10
推荐指数
1
解决办法
564
查看次数