1

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

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

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

今、私はそれをスレッドセーフにしたいと思っています。Java での double-checked-locking は「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;
            }
        }
    }
}

これを実際にスレッドセーフにするために何をしなければなりませんか?
いくつかのサブ質問:

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

(また、これはインスタンス メソッドであるため、静的初期化子は機能しないことに注意してください)

4

2 に答える 2

3

guava ライブラリSuppliers.memoize(Supplier<T> delegate)からの使用を検討することもできます。

于 2011-01-25T22:04:38.723 に答える
1

ダブルチェックの 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);
        }
    }
}
于 2010-10-09T18:05:50.307 に答える