3

私はこの記事を読みました:「ダブルチェックロックが壊れています」宣言、それは言う

ダブルチェック ロックは、マルチスレッド環境で遅延初期化を実装するための効率的な方法として広く引用され、使用されています。

残念ながら、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;
  }

}
4

1 に答える 1

1

あなたへの答え 1: はい。Java 5 以降のクラス ローダーは、静的フィールドの 1 回または 1 回の初期化を保証します。あなたの2への答え:コードからは明確ではありませんが、 wxMpConfigStorage.isJsapiTicketExpired() メソッドで何を読んでいるかによって異なります。スレッドセーフではないものを読んで決定した場合、はい DCL が失敗する可能性があります。しかし、あなたの場合、 jsapiTicketExpiresTime は揮発性であるため、読み取りがスレッドセーフであるため、DCL が機能します。

于 2015-01-26T15:19:11.520 に答える