本文介绍了对Java的final字段的值的“最新”保证是否扩展到间接引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java语言规范定义了:

The Java language spec defines semantics of final fields in section 17.5:

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

My question is - does the 'up-to-date' guarantee extend to the contents of nested arrays, and nested objects?

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

In a nutshell: If one thread assigns a mutable object graph to a final field in an object, and the object graph is never updated, can all threads safely read that object graph via the final field?

一个示例场景:


  1. 线程A构造一个ArrayList的HashMap,在类'MyClass'的实例中将HashMap分配给最终字段'myFinal'

  2. 线程B看到对MyClass实例的一个(非同步)引用,并读取'myFinal'并读取其中一个ArrayLists的内容

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

In this scenario, are the members of the ArrayList as seen by Thread B guaranteed to be at least as up to date as they were when MyClass's constructor completed?

我正在寻找Java内存模型和语言规范的语义的澄清,而不是替代解决方案如同步。

I'm looking for clarification of the semantics of the Java Memory Model and language spec, rather than alternative solutions like synchronization. My dream answer would be a yes or no, with a reference to the relevant text.

更新:


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

推荐答案

是的,它们是。

当第一次遇到引用时需要一个线程来读取内存。因为哈希映射是构造的,它中的所有条目都是全新的,那么对象的引用到当构造函数完成时它们是什么。

A thread is required to read memory when it encounters reference for the first time. Because hash map is constructed, all entries in it are brand new, then the references to objects are up-to-date to what they were when the constructor has finished.

在初次遇到后,通常的可见性规则适用。因此,当其他线程在最终引用中更改非最终字段时,其他线程可能看不到该更改,但它仍然会看到从构造函数中出来的引用。

After that initial encounter, the usual visibility rules apply. So, when other thread changes non-final field in the final references, the other thread may not see that change, but it still will see the reference that came out of constructor.

EDIT

EDIT

我知道我以前曾经看过这个保证。

I knew that I've seen this guarantee somewhere before.

来自此

新的JMM还试图提供
新的保证初始化安全
- 只要对象被正确构造(意味着
引用对象不是
在构造函数完成
之前发布)那么所有线程将看到
其最终字段的值
在其构造函数
中设置,无论
同步是否用于传递
引用从一个线程到另一个线程。
此外,可以是
的任何变量都通过
正确构造的对象的最终字段(例如
final字段引用的对象的
字段)也保证
对其他线程可见。这个
意味着如果最后一个字段包含一个
引用,比如一个LinkedList,在
中,除了
引用的正确值,其他的
是可见的线程,在构建时
LinkedList的内容
对于没有
同步的其他线程是可见的。结果是
显着增强
意义final - 最终字段
可以安全访问而不需要
同步,并且编译器
可以假定最终字段将不会
更改,因此可以优化离开
多次提取。

The new JMM also seeks to provide a new guarantee of initialization safety -- that as long as an object is properly constructed (meaning that a reference to the object is not published before the constructor has completed), then all threads will see the values for its final fields that were set in its constructor, regardless of whether or not synchronization is used to pass the reference from one thread to another. Further, any variables that can be reached through a final field of a properly constructed object, such as fields of an object referenced by a final field, are also guaranteed to be visible to other threads as well. This means that if a final field contains a reference to, say, a LinkedList, in addition to the correct value of the reference being visible to other threads, also the contents of that LinkedList at construction time would be visible to other threads without synchronization. The result is a significant strengthening of the meaning of final -- that final fields can be safely accessed without synchronization, and that compilers can assume that final fields will not change and can therefore optimize away multiple fetches.

这篇关于对Java的final字段的值的“最新”保证是否扩展到间接引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-27 16:11