执行‘;最新的&x2019;Java'值的保证;s的最终字段是否扩展到间接引用?
Java语言规范定义了中最终字段的语义: final字段的使用模型很简单。在对象的构造函数中设置对象的最终字段。在对象的构造函数完成之前,不要在另一个线程可以看到的地方编写对正在构造的对象的引用。如果遵循这一点,那么当另一个线程看到该对象时,该线程将始终看到该对象最终字段的正确构造版本。它还将看到最终字段引用的任何对象或数组的版本,这些版本至少与最终字段一样最新 我的问题是,“最新”保证是否扩展到嵌套数组和嵌套对象的内容 简言之:如果一个线程将可变对象图分配给对象中的最终字段,并且对象图从未更新,那么所有线程都可以通过最终字段安全地读取该对象图吗 一个示例场景:执行‘;最新的&x2019;Java'值的保证;s的最终字段是否扩展到间接引用?,java,memory,concurrency,synchronization,final,Java,Memory,Concurrency,Synchronization,Final,Java语言规范定义了中最终字段的语义: final字段的使用模型很简单。在对象的构造函数中设置对象的最终字段。在对象的构造函数完成之前,不要在另一个线程可以看到的地方编写对正在构造的对象的引用。如果遵循这一点,那么当另一个线程看到该对象时,该线程将始终看到该对象最终字段的正确构造版本。它还将看到最终字段引用的任何对象或数组的版本,这些版本至少与最终字段一样最新 我的问题是,“最新”保证是否扩展到嵌套数组和嵌套对象的内容 简言之:如果一个线程将可变对象图分配给对象中的最终字段,并且对象图从未更新
- 我对Java1.5及以上版本的语义感兴趣,即通过JSR133引入的更新Java内存模型。此更新中引入了对最终字段的“最新”保证李>
如果构造函数是这样编写的,那么应该没有问题:
public class MyClass {
public final Map myFinal;
public MyClass () {
Map localMap = new HashMap();
localMap.put("key", new ArrayList());
this.myFinal = localMap;
}
}
这是因为映射在分配给公共引用之前已完全初始化。一旦构造函数完成,最终的映射将是最新的。我担心的是对ArrayList中对象的陈旧引用,以及编译器的重新排序,例如在ArrayList完全初始化之前在HashMap中提供ArrayList实例。我很想知道在将可变对象图分配给最终字段时提供了什么样的排序保证。@mattbh。如果可变对象在构造函数调用之前就已经存在,那么通常的可见性约束将适用,但是所有线程看到的最终引用将指向同一个对象。不过,在没有同步的情况下,每个线程可能会看到它有点不同。@Alexander。谢谢你的回答。规范中是否有任何内容阻止编译器在初始化这些内部对象的(非最终)字段之前使其引用可用?对于非最终字段,编译器通常可以自由执行此操作。Java规范第17.5节中的FinalFieldExample类说明了如何允许这种重新排序。@mattbh。如果您没有通过与其他线程共享半构造的对象(比如通过在构造函数或初始值设定项中传递
this
)来打击自己,那么除了调用线程之外,没有人会看到非final字段的更新。在同一线程的上下文中,它可以看到字段的最新值。FinalFieldExample
显示退出构造函数后可能遇到的问题