【问题标题】:Is double-checked locking only broken in a lazy initialization scene?双重检查锁定是否仅在惰性初始化场景中被破坏?
【发布时间】:2015-01-24 12:35:22
【问题描述】:

我读了这篇文章:The "Double-Checked Locking is Broken" Declaration,上面写着

双重检查锁定被广泛引用并用作一种有效的方法 用于在多线程环境中实现延迟初始化。

不幸的是,它不能以独立于平台的方式可靠地工作 在 Java 中实现时...

这篇文章:Double-checked locking: Clever, but broken,上面写着:

DCL 习惯用法旨在支持延迟初始化...

我的问题是:

  1. 只有在尝试进行延迟初始化时才会破坏双重检查锁定吗?

  2. 是不是也像下面代码这样的场景坏了(所有东西都已经初始化了)?

代码:

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


【解决方案1】:

回答你的 1:是的。从 Java 5 开始,类加载器保证静态字段的单次或一次性初始化。 回答您的 2:从代码中不清楚,但这取决于您在 wxMpConfigStorage.isJsapiTicketExpired() 方法中阅读的内容。如果您根据读取不是线程安全的内容来决定,那么是的,DCL 可能会失败。但在你的情况下,jsapiTicketExpiresTime 是易变的,因此线程安全读取,因此 DCL 将为你工作。

【讨论】:

  • 谢谢@Mark,isJsapiTicketExpired 方法是: public synchronized void isJsapiTicketExpired() { return System.currentTimeMillis() > jsapiTicketExpiresTime; }。而且,我对这个结论是否正确? DCL是否安全取决于:1)检查方法线程安全吗? 2)在惰性初始化中,是否有可能重新排序a = new B()?。
猜你喜欢
  • 2011-08-22
  • 1970-01-01
  • 2017-07-20
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多