Fan*_*hen 6 java immutability thread-safety double-checked-locking
在http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html的底部,它说:
双重检查锁定不可变对象
如果Helper是一个不可变对象,使得Helper的所有字段都是最终的,那么双重检查锁定将无需使用volatile字段即可工作.我们的想法是对不可变对象(如String或Integer)的引用应该与int或float的行为方式大致相同; 读取和写入对不可变对象的引用是原子的.
可变的样本和解释如下:
// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null)
synchronized(this) {
if (helper == null)
helper = new Helper();
}
return helper;
}
// other functions and members...
}
Run Code Online (Sandbox Code Playgroud)
它不起作用的第一个原因
最明显的原因是,初始化Helper对象和写入辅助对象字段的写入可以无序完成或感知.因此,调用getHelper()的线程可以看到对辅助对象的非null引用,但是请参阅辅助对象的字段的默认值,而不是构造函数中设置的值.
如果编译器内联对构造函数的调用,那么如果编译器可以证明构造函数不能抛出异常或执行同步,则可以自由地重新排序初始化对象和写入辅助对象字段的写入.
即使编译器没有重新排序这些写入,在多处理器上,处理器或内存系统也可能重新排序这些写入,正如在另一个处理器上运行的线程所感知的那样.
我的问题是:为什么不可变类没有问题?我看不出重新排序与该类是否可变的任何关系.
谢谢
不可变类确实有问题。在 JSR133 中对 Java 内存进行更改 后,您引用的部分是正确的。
具体来说,影响不可变对象的更改与对关键字所做的一些更改有关final。查看http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight。
重要的部分是:
对象的最终字段的值在其构造函数中设置。假设该对象被“正确”构造,一旦构造了一个对象,分配给构造函数中的最终字段的值将对所有其他线程可见,而无需同步。
| 归档时间: |
|
| 查看次数: |
419 次 |
| 最近记录: |