Тот факт, что этот метод задокументирован как atomic
, не имеет большого значения для visibility
(если это не является частью документации).Например, чтобы сделать это проще:
// some shared data
private List<Integer> list = new ArrayList<>();
public synchronized void addToList(List<Integer> x){
list.addAll(x);
}
public /* no synchronized */ List<Integer> getList(){
return list;
}
Мы можем сказать, что addToList
действительно атомарный, только один поток может вызвать его за один раз.Но как только определенный поток вызывает getList
- просто нет гарантии относительно visibility
(потому что для того, чтобы это установить, это должно произойти с той же блокировкой ).Таким образом, видимость - это то, что происходит до того, как дело касается, и документация computeIfPresent
ничего об этом не говорит.
Вместо этого документация класса гласит:
Операции получения (включая получение) обычно не блокируются, поэтому может перекрываться с операциями обновления (включая операции удаления и удаления),
Ключевым моментом здесь, очевидно, является перекрытие , поэтому некоторые другие потоки, вызывающие get
(получая, таким образом, List
), могут видеть, что List
вкакое-то государство;не обязательно состояние, в котором computeIfPresent
начался (до того, как вы на самом деле позвонили get
).Обязательно прочитайте дальше, чтобы понять, что на самом деле может означать some .
А теперь самое сложное в этой документации:
Извлечения отражают результаты самых последних завершенных операций обновления, проведенных с момента их появления.Более формально, операция обновления для данного ключа имеет отношение случай-до с любым (не нулевым) поиском для этого ключа, сообщающего обновленное значение.
Прочитайте это предложениео завершено снова, то, что он говорит, это то, что единственное, что вы можете прочитать, когда поток get
это последний завершенный состояние, в котором был List. И теперь следующее предложение говоритчто происходит до , установленного между двумя действиями.
Подумайте об этом, happens-before
устанавливается между двумя последующими действиями (как в синхронизированном примере выше);так что внутренне, когда вы обновляете Key
, может быть изменчивая письменная сигнализация, что обновление завершено (я почти уверен, что это не так, просто пример).Для того чтобы случившееся действительно сработало, get
должен прочитать это изменчивое и увидеть состояние, которое было ему записано;если он видит это состояние, это означает, что происходит до того, как было установлено;и я предполагаю, что с помощью какой-то другой техники это фактически выполняется.
Итак, чтобы ответить на ваш вопрос, все потоки, вызывающие get
, увидят last completed action
, произошедшую с этим ключом;в вашем случае, если вы можете гарантировать этот порядок, я бы сказал, да, они будут видны.