質問

これは私のコードが現在どのように見えるかです:

private boolean[] isInitialized = new boolean[COUNT];

private void ensureInitialized(int i) {
    if (! isInitialized[i]) {
        initialize(i);
        isInitialized[i] = true;
    }
}

今、私はそれをスレッドセーフにしたいです。 Javaでのダブルチェックロックは「Teh 3Vilness !! 1」であることを知っていますが、それ以来 ensureInitialized 非常に頻繁に呼ばれるかもしれませんが、私はそれを同期させたくありません。だから私はこれをすることを考えています:

private boolean[] isInitialized = new boolean[COUNT];

private void ensureInitialized(int i) {
    if (! isInitialized[i]) {
        synchronized (this) {
            if (! isInitialized[i]) {
                initialize(i);
                isInitialized[i] = true;
            }
        }
    }
}

これで、これを実際に安全にするために何をしなければなりませんか?
いくつかのサブクエスト:

  • 作り isInitialized 変数が変更されないため、揮発性は必要ありませんよね?
  • 配列要素が変更されますが、どうすればそれらを揮発性にすることができますか?
  • 一般的にこれを行うより良い方法はありますか?

(これはインスタンスメソッドであるため、静的イニシャルは作業を行わないことに注意してください)

役に立ちましたか?

解決

ダブルチェックのJavaの実装は、失敗として証明されているため、「壊れたパターン」と呼ばれることに注意してください(たとえば、参照 http://www.cs.umd.edu/~pugh/java/memorymodel/doublecheckedlocking.html)。回避するには、原子動作を使用するだけです。フォローはサンプルのサンプルであり、安全なシングルトンを構築する方法です。

static AtomicReferenceArray<Boolean> instance = 
   new AtomicReferenceArray<Boolean>(COUNT);

private void ensure(int i)
{
    if(!instance.get(i) )
    {
        synchronized(this){
        if( !instance.get(i) ){
           initialize(i);
           instance.set(i, true);
        }
    }
}

他のヒント

使用を検討することもできます Suppliers.memoize(Supplier<T> delegate) から グアバ図書館.

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