Конечные ссылки на объекты — гарантируется ли видимость между всеми потоками?

Я читал эту статью:

https://www.javamex.com/tutorials/synchronization_final.shtml

В нем говорилось:

Поля любого объекта, доступ к которому осуществляется через конечную ссылку, также гарантированно будут как минимум такими же актуальными, как и при выходе из конструктора. Это означает, что: Значения полей final, включая объекты внутри коллекций, на которые ссылается конечная ссылка, можно безопасно считывать без синхронизации.

Скажем, у меня есть класс, как показано ниже:

public class Cache {


private Map<String, Currency> currencyMap = new ConcurrentHashMap<String, Currency>();
private List<Currency> currencyList = new ArrayList<Currency>();
}

Если я объявлю в своем основном классе приложения:

private final Cache cache;

Означает ли это, что если поток A обновит currencyMap и currencyList, то это гарантирует, что поток B увидит последние записи в currencyMap и currencyList?


person user3809938    schedule 06.02.2019    source источник
comment
Это означает, что ThreadA и ThreadB будут видеть один и тот же экземпляр currencyMap. Содержимое currencyMap, которое видят ThreadA и ThreadB, может быть разным, но экземпляр currencyMap одинаков.   -  person    schedule 06.02.2019
comment
Если вы беспокоитесь об актуальности содержимого встроенных объектов между потоками, объявите private final AtomicReference<Cache> cache; в своем основном классе.   -  person j.seashell    schedule 06.02.2019


Ответы (1)


Нет такой гарантии, что ThreadB увидит обновления, сделанные для currencyList ThreadA. Гарантия, которую вы получаете с

private final Cache cache;

в том, что кеш благополучно опубликован. Это означает, что читатели/другие потоки будут наблюдать кеш как правильно построенный объект (в вашем случае currencyMap и currencyList не будут нулевыми и будут правильно построены).

Если ThreadA изменяет валютный список, нет никакой гарантии, что ThreadB увидит новые значения. Для этого вам нужно будет синхронизировать доступ к валютному списку.

currencyMap — это ConncurrentHashMap, который является потокобезопасным классом (методы, которые изменяют состояние карты, внутренне синхронизированы). Если вы никогда не измените ссылку на currencyMap (вы никогда не назначите какую-либо другую карту этой ссылке), то вам не нужно синхронизировать доступ к этой карте (поскольку кеш безопасно опубликован), но лучше было бы объявить currencyMap как окончательный (это гарантирует, что ссылка не будет переназначена).

person HPCS    schedule 01.04.2019