【发布时间】:2011-02-07 21:15:47
【问题描述】:
这个问题与旧 Java 版本的行为和双重检查锁定算法的旧实现有关
较新的实现 use volatile 并依赖于稍微改变的 volatile 语义,因此它们没有损坏。
声明字段分配始终是原子的,除了 long 或 double 的字段。
但是,当我读到为什么双重检查锁定被破坏的解释时,据说问题在于赋值操作:
// 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...
}
- 线程 A 注意到该值未初始化,因此它获取 锁定并开始初始化 价值。
- 由于某些编程语言的语义,代码 允许编译器生成 更新共享变量指向 到一个部分构造的对象 在 A 完成执行之前 初始化。
- 线程 B 注意到共享变量已被初始化(或 它出现),并返回其值。 因为线程 B 认为值是 已经初始化,它没有 获取锁。如果 B 使用对象 在所有初始化完成之前 A 被 B 看到(或者因为 A 尚未完成初始化或 因为一些初始化值 在物体中尚未渗出 到内存 B 使用(缓存 连贯性)),该程序可能 碰撞。
(来自http://en.wikipedia.org/wiki/Double-checked_locking)。
什么时候可以? 64位JVM分配操作是否可能不是原子的? 如果不是,那么“双重检查锁定”是否真的被破坏了?
【问题讨论】:
标签: java multithreading synchronization locking anti-patterns