У меня есть вопрос о видимости в java. Видимость может появиться только в том случае, если у нас есть как минимум два потока, которые работают как минимум на 2 ядрах процессора. Это правильно? Каждое ядро может кэшировать переменные в своих регистрах и кэш-памяти, из-за чего могут возникнуть проблемы с видимостью. Но что, если у нас есть n потоков и все они работают на одном ядре процессора (конечно, мы не можем быть уверены, что они будут работать только на одном ядре, но предположим, что это возможно), то нет никакого способа иметь видимость памяти? Или это не правильно? Заранее спасибо.
Видимость параллелизма Java
Ответы (2)
Если под видимостью понимать разделяемую память, чтобы объекты, которые создаются или изменяются в одном потоке, могли быть видны и в другом потоке, то сколько бы ядер ни было, видимость останется прежней. Java дает обещания в соответствии с Спецификацией языка Java, в частности Модель памяти Java, которой необходимо следовать независимо от количества ядер.
Но что, если у нас есть n потоков и все они работают на одном ядре процессора (конечно, мы не можем быть уверены, что они будут работать только на одном ядре, но предположим, что это возможно), то нет никакого способа иметь видимость памяти? Или это не правильно?
Да, видимость (общая память) по-прежнему существует, если на одном ядре работает n потоков. Но есть некоторые предостережения, которые существуют независимо от того, сколько ядер. Главным образом то, что каждый поток имеет свою собственную кэшированную память, и переменная может иметь разные значения в обоих потоках. Если переменная volatile
, то значение этой переменной всегда будет обновляться во всех потоках.
Поле может быть объявлено volatile, и в этом случае модель памяти Java гарантирует, что все потоки видят согласованное значение переменной (§17.4).
Я рекомендую вам больше узнать о модели памяти Java.
Даже на 1 ядре с несколькими потоками у вас все еще может быть то, что вы называете этой проблемой «видимости», поскольку потоки, которые загрузили значение из памяти в регистр, сохранят это значение в стеке этого потока и не увидят обновление, если поток выключается, а затем снова включается, если переменная/память объявлена volatile