【发布时间】:2015-01-24 12:35:22
【问题描述】:
我读了这篇文章:The "Double-Checked Locking is Broken" Declaration,上面写着
双重检查锁定被广泛引用并用作一种有效的方法 用于在多线程环境中实现延迟初始化。
不幸的是,它不能以独立于平台的方式可靠地工作 在 Java 中实现时...
这篇文章:Double-checked locking: Clever, but broken,上面写着:
DCL 习惯用法旨在支持延迟初始化...
我的问题是:
只有在尝试进行延迟初始化时才会破坏双重检查锁定吗?
是不是也像下面代码这样的场景坏了(所有东西都已经初始化了)?
代码:
public String refreshJsapiTicket() throws WxErrorException {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
synchronized (wxMpConfigStorage) {
if (wxMpConfigStorage.isJsapiTicketExpired()) {
// ...
// update
wxMpConfigStorage.setJsapiTicket(jsapiTicket, expiresInSeconds);
}
}
}
}
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected volatile String jsapiTicket;
protected volatile long jsapiTicketExpiresTime;
public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
this.jsapiTicket = jsapiTicket;
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
}
}
【问题讨论】:
-
请阅读全文。从 JDK5 开始,如果正确实施,双重检查锁定确实有效。 (也就是说,将检查和变异的字段声明为
volatile。)但是在许多情况下,您可以做得更好,只需使用AtomicReference和朋友。 -
@biziclop 非常感谢。另一个问题,如果我使用 jdk1.4,DCL 在第二个问题的示例代码中是否有效?
-
AtomicReference习语不能保证初始化代码只运行一次。由于延迟初始化主要是为了延迟重量级初始化,直到它被证明需要,AtomicReference的适用性变得非常值得怀疑。另一方面,惰性初始化持有者类习语提供相同的保证,但比 DCL 更脆弱。
标签: java multithreading double-checked-locking