に格納されている共有リソースを初期化するためにI/Oバウンド操作を実行する必要がある複数のスレッドで実行できるコードがありますConcurrentMap。このコードスレッドを安全にし、共有リソースを初期化するための不要な呼び出しを回避する必要があります。バグのあるコードは次のとおりです。
private ConcurrentMap<String, Resource> map;
// .....
String key = "somekey";
Resource resource;
if (map.containsKey(key)) {
resource = map.get(key);
} else {
resource = getResource(key); // I/O-bound, expensive operation
map.put(key, resource);
}
上記のコードを使用すると、複数のスレッドがをチェックしてリソースが存在しないことを確認し、すべてが高額なConcurrentMap呼び出しを試みる可能性があります。getResource()共有リソースの単一の初期化のみを保証し、リソースが初期化された後にコードを効率的にするために、私は次のようなことをしたいと思います。
String key = "somekey";
Resource resource;
if (!map.containsKey(key)) {
synchronized (map) {
if (!map.containsKey(key)) {
resource = getResource(key);
map.put(key, resource);
}
}
}
これはダブルチェックロックの安全なバージョンですか?チェックが呼び出されるので、チェックConcurrentMapは宣言された共有リソースのように動作し、volatile発生する可能性のある「部分的な初期化」の問題を防ぐように思われます。