Упорядочение памяти, другое исполнение и многопоточная безопасность

Я читал на память переупорядочения в последнее время. Мой вопрос касается многопоточных сценариев. Рассмотрим пример ниже:

A = 0;
B = 0;

Thread 1 on Processor 1                       Thread 2 on Processor 2

    A = 100;                                      while(B== 0);
    B = 1;                                       //access A here

Я программировал на платформах Windows X86-64 и никогда не думал, что хранилища в A и B могут быть переупорядочены (либо на уровне компилятора, либо на аппаратном уровне), и я могу в итоге получить B = 0 в потоке 2 и найти A все еще 0. И никогда не сталкивался с какими-либо проблемами или неприятными ошибками с таким кодом. Это потому, что x86-x64 строго упорядочены, как и компиляторы Windows C.

Чтобы такой код выполнялся на любой другой платформе со слабо упорядоченной памятью, мне нужно убедиться, что я обновляю и обращаюсь к A и B в пределах блокировки (предполагая, что базовая реализация блокировки использует барьеры памяти и гарантирует, что блокировка снята только после все предыдущие загрузки и хранилища видны на всех процессорных ядрах).

Спасибо

1 ответ

Это потому, что x86-x64 строго упорядочены, как и компиляторы Windows C.

В самом деле, X86 является строго упорядоченным процессором, который не позволяет переупорядочивать магазин. Таким образом, все ядра ЦП будут соблюдать порядок, сгенерированный компилятором.

Тем не мение, B модифицируется на процессоре 1, а считывается на процессоре 2. Это не допускается моделью памяти C без синхронизации (попробуйте максимальную оптимизацию компилятора, она может перестать работать).

Хотя блокировка может использоваться для синхронизации между ядрами, это может быть проблематично, так как вы вращаетесь на B, Если это происходит с полученной блокировкой, процессор 1 не может обновить значение.

Правильное решение состоит в том, чтобы сделать Batomic, Это гарантирует правильный порядок на всех уровнях.

Другие вопросы по тегам