3

我读了这篇文章:“双重检查锁定被破坏”声明,它说

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

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

而这篇文章:双重检查锁定:聪明,但坏了,它说:

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;
  }

}
4

1 回答 1

1

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

于 2015-01-26T15:19:11.520 回答