Java:配列要素でダブルチェックロックを行うにはどうすればよいですか?
-
29-09-2019 - |
質問
これは私のコードが現在どのように見えるかです:
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)
から グアバ図書館.
所属していません StackOverflow