質問

このコードは、Javaの二重チェックロック問題を解決しますか?

public class DBAccessService() {
    private static DBAccessService INSTANCE;  

    private DBAccessService() {}

    public static DBAccessService getInstance() {
        if (INSTANCE != null) {
            return INSTANCE;
        }
        return createInstance();
    }

    private static synchronized DBAccessService createInstance() {
        if (INSTANCE != null) {
            return INSTANCE;
        }
        DBAccessService instance = new DBAccessService();
        INSTANCE = instance;

        return INSTANCE;
    }
}
.

注意を払うための2つの側面があります:

  1. getInstance()ではなく同期されているので、インスタンスが初期化された後、同期のコストはありません
  2. createInstance()は同期

    だから、問題は次のとおりです。このコードには問題がありますか?それは合法的で常にスレッドセーフ?

役に立ちましたか?

解決

この質問を解決するための Java並行性(基本的にjava.utilを書いたチームによって書かれた.concurrent図書館遅延初期化ホルダークラスIDIOM (16.6ページのコピーの中で、 16.7)

@ThreadSafe
public class DBAccessServiceFactory {
  private static class ResourceHolder {
    public static DBAccessService INSTANCE = new DBAccessService();
  }
  public static DBAccessService getResource() {
    return ResourceHolder.INSTANCE;
  }
}
.

これは常に合法でスレッドセーフです。私は専門家ではないので、これはあなたのコードよりも優れていると言うことができません。しかし、それがDoug LeaとJoshua Blochによって推奨されるパターンであることを考えると、私はあなたが常にあなたまたは私が発明しました、そして私はそれが間違いを作るのがとても簡単であるので(この質問に対する間違った回答の数によって示されるように) )

彼らが言う揮発性の問題に関連しています:

JMM(Java 5.0以降)の変更は、リソースが揮発性にされている場合はDCLが機能することができました...しかし、LAZY初期化ホルダーのIDIOMは同じ利点を提供し、理解しやすいです。

他のヒント

INSTANCEvolatileとして宣言する必要があります。

private static volatile DBAccessService INSTANCE;
.

注Java 5以降でのみ機能します。「ダブルチェックロックは壊れています」宣言

はうまく見えます。 2つのスレッド呼び出し()とインスタンスが発信されていない場合は、createInstance()を続行することができるスレッドが1つだけであり、2番目のスレッドはすでにインスタンスがNULLではないことがわかります。

唯一のものは、例えばvolatileキーワードです。それ以外の場合、Javaはそれをキャッシュできます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top