У меня есть фрагмент кода, который может выполняться несколькими потоками и которому необходимо выполнить операцию ввода-вывода, чтобы инициализировать общий ресурс, хранящийся в ConcurrentMap. Мне нужно сделать этот код безопасным и избежать ненужных вызовов для инициализации общего ресурса. Вот код ошибки:
Код: Выделить всё
private ConcurrentMap 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, он ведет себя как общий ресурс, объявленный изменчивым, и, таким образом, предотвращает любые проблемы «частичной инициализации», которые могут возникнуть.
Подробнее здесь:
https://stackoverflow.com/questions/700 ... currentmap