Гарантирует ли JVM / x86 энергонезависимое распространение значений по ядрам? - PullRequest
2 голосов
/ 06 мая 2019

Предполагая следующий код:

class X {
    private int v = 1;
    public void set(int v) { this.v = v; }
    public int get() { return v; }
}

существует ли вероятность того, что, не пометив v как энергозависимый, при вызове set(123) его значение не будет распространяться на другие ядра (то есть ихкэширования и / или основной памяти), или это просто вопрос времени, пока это не произойдет?

Обсуждая вопрос, общая идея, как представляется, заключается в том, что рано или поздно значение «попадет туда», поэтомудо тех пор, пока нам не нужно слишком много времени, можно оставить значение неизменным, но я хотел быть формально уверенным.

Насколько я понимаю, семантика получения / выпуска отсутствует,JMM не гарантирует, что это сработает, но, с другой стороны, мое (ограниченное) понимание моделей когерентности / согласованности кэша (а именно TSO-x86) заключается в том, что он обязательно будет в конечном итоге распространяться (пометив его как volatile, просто поместитзабор, чтобы запретить переупорядочения в буфере хранения ЦП, но кроме этого он в конечном итоге будет распространен на другие кэши).В связи с этим есть только один момент, который заставляет меня задуматься - что произойдет, если другое ядро ​​записывает что-то в другую переменную в той же строке кэша?Может ли он в любом случае перезаписать v?

Может ли кто-нибудь, знающий в этих вопросах, дать мне более конкретный ответ?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 06 мая 2019

Опасность рассуждать о правильности вашего кода опасна, если взглянуть на основные детали реализации конкретной архитектуры.JMM не дает никаких гарантий видимости между потоками для энергонезависимого доступа.Тот факт, что он может работать, не означает, что он всегда гарантированно работает.

Кроме того, в вашем анализе отсутствует то, что может сгенерировать компилятор.Компилятор может кэшировать значения в регистре, может производить «ложные» чтения или записи, которые не влияют на корректность однопоточных программ, но нарушают многопоточные программы и т. Д.

Если вы хотите гарантироватьвидимость потоков без использования volatile, взгляните на непрозрачный режим доступа Java 9.

2 голосов
/ 06 мая 2019

Согласно модели памяти JVM, в вашем примере нет отношения случай-до .Таким образом, формально нет гарантии, что другой поток будет когда-либо видеть обновления общих переменных.

Полагаться на детали реализации конкретной JVM и архитектуры процессора мне не кажется хорошей идеей.То, что работает сегодня в лаборатории, завтра может выйти из строя.Также обратите внимание, что в конечном итоге может занять очень много времени, поскольку для него нет верхней границы.На самом деле я сталкивался с случаями, когда моя программа, казалось бы, блокировалась из-за отсутствия volatile аннотаций и должна была быть перезапущена.

...