次のJavaコードを使用します。
public class SomeClass {
private boolean initialized = false;
private final List<String> someList;
public SomeClass() {
someList = new ConcurrentLinkedQueue<String>();
}
public void doSomeProcessing() {
// do some stuff...
// check if the list has been initialized
if (!initialized) {
synchronized(this) {
if (!initialized) {
// invoke a webservice that takes a lot of time
final List<String> wsResult = invokeWebService();
someList.addAll(wsResult);
initialized = true;
}
}
}
// list is initialized
for (final String s : someList) {
// do more stuff...
}
}
}
秘訣は、doSomeProcessing
特定の条件下でのみ呼び出されることです。リストの初期化は非常に費用のかかる手順であり、まったく必要ない場合があります。
ダブルチェックのイディオムが壊れている理由についての記事を読んだことがあり、このコードを見たときは少し懐疑的でした。ただし、この例の制御変数はブール値であるため、私が知る限り、単純な書き込み命令が必要です。
someList
また、がとして宣言されfinal
、同時リストへの参照を保持しwrites
て いることに注意してくださいreads
。ConcurrentLinkedQueue
リストの代わりに単純なArrayList
またはLinkedList
、として宣言されている場合でも、発生する必要はありませfinal
ん-の前に。writes
reads
それで、上記のコードはデータの競合がないのですか?