Упорядочение памяти, другое исполнение и многопоточная безопасность
Я читал на память переупорядочения в последнее время. Мой вопрос касается многопоточных сценариев. Рассмотрим пример ниже:
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 не может обновить значение.
Правильное решение состоит в том, чтобы сделать B
atomic
, Это гарантирует правильный порядок на всех уровнях.