双重检查锁定是否仅在惰性初始化场景中被破坏?

Is double-checked locking only broken in a lazy initialization scene?

我读了这篇文章:The "Double-Checked Locking is Broken" Declaration,它说

Double-Checked Locking is widely cited and used as an efficient method for implementing lazy initialization in a multithreaded environment.

Unfortunately, it will not work reliably in a platform independent way when implemented in Java...

而这篇文章:Double-checked locking: Clever, but broken,它说:

The DCL idiom was designed to support lazy initialization...

我的问题是:

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

}

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