Я читаю о модели памяти Java в JSR-133 и не могу понять, насколько приемлем такой тип поведения:
введите описание изображения здесь

Может кто-нибудь объяснить это?

2
Hlib 11 Окт 2021 в 12:42

2 ответа

Лучший ответ

ЕДИНСТВЕННОЕ, что должен гарантировать ЦП, - это то, что запись в X внутри потока НЕ ​​влияет на последующее присвоение связанной с ним области памяти RX. Он ничего не говорит о том, откуда он берет значение, из которого собирается писать.

Так, В потоке 1 ЦП сообщает
«Ох, мне нужно прочитать X», поэтому начинается операция чтения.
Затем он говорит
«И мне нужно написать в X», поэтому затем ОЧЕРЕДИ значение в очереди записи

Поток 2 делает то же самое.
«Ох, мне нужно прочитать X» - и начинается чтение.
«Мне нужно написать в X» и ставит запись в очередь.

Теперь у нас есть два ожидающих чтения и две записи в очереди.

Если в архитектуре ЦП указано, что чтение на одном ядре может опрашивать очередь записи другого ядра, то оба ядра могут читать друг друга, ожидающие записи в X. Следовательно, вы получаете два значения, которые протягиваются между ядрами, и в конечном итоге назначаются ячейке памяти RX из эта нить.

Когда вы устанавливаете барьеры памяти в поток инструкций, это предотвращает этот тип чрезмерно нетерпеливого чтения записи в очереди.

1
Ben Seidel 11 Окт 2021 в 14:12

8.1 Удивительное поведение, допускаемое моделью памяти

На рисунке 12 показан небольшой, но интересный пример. Поведение r1 == 2 и r2 == 1 является допустимым, хотя может быть трудно понять, как это могло произойти. Компилятор не меняет порядок операторов в каждом потоке; этот код никогда не должен приводить к r1 == 1 или r2 == 2. Однако поведение r1 == 2 и r2 == 1 может быть разрешено архитектурой процессора, которая выполняет запись раньше, но таким образом, что они не были видны локальным операциям чтения, предшествовавшим им в программном порядке. Такое поведение, хотя и удивительное, разрешено моделью памяти Java. Чтобы получить этот результат в модели памяти, мы фиксируем обе записи, за которыми следуют оба чтения.

Почему-то ЦП решил записать x раньше, чем читать x. В этом примере говорится, что это допустимое поведение, более или менее, это исключение, которое принимается как допустимое поведение.

Процессор Intel Itanium может вызывать такое поведение.

Так что вместо:

//Thread 1
int x = 0;
int r1 = x;
x = 1;

//Thread 2
int x = 0;
int r2 = x;
x = 2;

Это случилось:

//Thread 1
int x = 0;
x = 2; //from Thread 2
int r1 = x;

//Thread 2
int x = 0;
x = 1; //from Thread 1
int r2 = x;

И это абсолютно верно. (Принятое исключение.)

0
paladin 11 Окт 2021 в 12:58