Double-checked locking: Clever, but breakedなどのさまざまな記事を読み、次のコードがマルチスレッドの使用で壊れている理由を理解しました。
class SomeClass {
private Resource resource = null;
public Resource getResource() {
if (resource == null) {
synchronized {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
ただし、その説明によると、スレッドが同期ブロックを終了すると、書き込みバリアが実行されます。ロックを解放する前に、そのブロックで変更されたすべての変数をメイン メモリにフラッシュする必要があります。したがって、スレッド A が同期ブロックに実行されると、次のプロセスが順番に実行されます。
- 新しい Resource オブジェクトのメモリが割り当てられます。
- Resource のコンストラクタが呼び出され、
- 新しいオブジェクトのメンバー フィールドを初期化します。
- SomeClass のフィールド リソースには、新しく作成されたオブジェクトへの参照が割り当てられます。
最後に、スレッド A が同期ブロックから出る前に、スレッド A はそのローカル リソース オブジェクトをメイン メモリに書き戻し、スレッド B は、同期ブロックに到達すると、この新しく作成されたリソースをメイン メモリから読み取ります。
スレッド B がこれらのメモリ操作を、スレッド A が実行する順序とは異なる順序で見ることができるのはなぜですか? スレッド B は、共有可能なメイン メモリからしかリソース オブジェクトを読み取ることができないため、スレッド A が同期ブロックから出るときにローカル メモリをメイン メモリにフラッシュするまで、リソース オブジェクトが作成されたことをスレッド B は認識しないと思いましたか?
私の理解を修正してください....ありがとうございます。