mat*_*tbh 10 java memory concurrency synchronization final
Java语言规范定义了第17.5节中最终字段的语义:
最终字段的使用模型很简单.在该对象的构造函数中设置对象的最终字段.在对象的构造函数完成之前,不要在另一个线程可以看到的位置写入对正在构造的对象的引用.如果遵循此原因,那么当另一个线程看到该对象时,该线程将始终看到该对象的最终字段的正确构造版本.它还将看到那些最终字段引用的任何对象或数组的版本,这些字段至少与最终字段一样是最新的.
我的问题是 - '最新'保证是否扩展到嵌套数组和嵌套对象的内容?
简而言之:如果一个线程将可变对象图分配给对象中的最终字段,并且对象图永远不会更新,那么所有线程都可以通过最终字段安全地读取该对象图吗?
示例场景:
在这种情况下,线程B看到的ArrayList的成员是否保证至少与MyClass的构造函数完成时一样最新?
我正在寻找澄清Java内存模型和语言规范的语义,而不是像同步这样的替代解决方案.我的梦想答案是肯定或否定,并参考相关文字.
更新:
在这种情况下,线程B看到的ArrayList的成员是否保证至少与MyClass的构造函数完成时一样最新?
对,他们是.
第一次遇到引用时,需要一个线程来读取内存.因为构造了哈希映射,所以其中的所有条目都是全新的,然后对对象的引用up-to-date就是构造函数完成时的引用.
在初次遭遇之后,通常的可见性规则适用.因此,当其他线程更改最终引用中的非final字段时,另一个线程可能看不到该更改,但仍会看到构造函数中的引用.
实际上,这意味着如果您不在构造函数之后修改最终哈希映射,则其内容是所有线程的常量.
编辑
我知道我以前见过这个保证.
初始化安全
新的JMM还试图提供初始化安全性的新保证 - 只要对象被正确构造(意味着在构造函数完成之前未发布对象的引用),那么所有线程都将看到值它的最终字段是在其构造函数中设置的,无论是否使用同步将引用从一个线程传递到另一个线程.此外,任何可以通过正确构造的对象的最终字段到达的变量,例如最终字段引用的对象的字段,也保证对其他线程也是可见的.这意味着如果final字段包含对LinkedList的引用,除了对其他线程可见的引用的正确值之外,构造时该LinkedList的内容对于没有同步的其他线程也是可见的.结果是最终意义的显着增强 - 最终字段可以在没有同步的情况下安全地访问,并且编译器可以假设最终字段不会改变,因此可以优化多个提取.
| 归档时间: |
|
| 查看次数: |
564 次 |
| 最近记录: |