次の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ん-の前に。writesreads
それで、上記のコードはデータの競合がないのですか?