Операции только для чтения являются потокобезопасными по определению.Условие гонки или гонки данных произойдет, только если есть хотя бы один поток, который изменяет данные.
Так что, если вы поместите значение в карту, прежде чем создавать поток, который считывает значение из карты,тогда операция полностью безопасна.И если вы никогда не изменяете bar или его ссылки внутри foo, у вас тоже все будет хорошо.Вам даже не нужна параллельная карта в этом случае.Обычная карта просто подойдет.
Однако вы можете получить неожиданные результаты, если bar модифицируется или если ссылка на bar изменяется внутри foo.Вот пример чего-то, что может пойти не так.Предположим, что bar - это long
.
class Foo {
public long bar;
}
И у вас есть поток 1, который делает:
Foo foo = concurrentMap.get("key");
.....
..... /// some code
System.out.println(foo.bar);
И есть еще один поток в фоновом режиме, который делает это:
Foo foo = concurrentMap.get("key");
.....
long newBar = foo.bar + 1;
foo.bar = newBar;
Здесь у вас прямое состояние гонки.
Теперь, если поток 2 фактически просто делает это вместо этого:
Foo foo = concurrentMap.get("key");
.....
long newBar = rand.nextLong();
foo.bar = newBar;
У вас нет условия гонки, но у вас естьвместо этого - гонка данных, потому что long - это 64-битная версия, и компилятор может выполнить присвоение long и double как две операции.
Есть много других сценариев, где это может пойти не так, и действительно труднорассуждать о них, не очень осторожно
Так что, по крайней мере, вы должны сделать бар изменчивым, как это:
class Foo {
public volatile Object bar;
}
И быть очень осторожным в том, как вы работаете на баре и чтовнутри, если это реальный объект какого-то класса.
Если вы хотите больше узнать о гонках с данными и лучше понять условия гонки, вам следует проверить этот превосходный курс https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
Имеет секретоб этом, это объясняет это очень хорошо, с действительно хорошими примерами.
Вы также должны проверить официальную документацию модели памяти Java https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4
Надеюсь, это поможет