К сожалению, изменчивая семантика довольно размыта. Концепция volatile на самом деле не предназначалась для использования в многопоточности.
Potatoswatter прав в том, что вызов примитивов синхронизации ОС обычно не позволяет оптимизирующему компилятору поднять чтение num из цикла. Но это работает по той же причине, по которой работает метод доступа... случайно.
Компилятор видит, что вы вызываете функцию, которая не сразу доступна для встраивания или анализа, поэтому он должен предположить, что любая переменная, которая может использоваться какой-либо другой функцией, может быть прочитана или изменена в этой непрозрачной функции. Поэтому перед выполнением вызова компилятору необходимо записать все эти «глобальные» переменные обратно в память.
В corensic мы добавили встроенную функцию в jinx.h, которая делает это более прямым способом. Что-то вроде следующего:
inline void memory_barrier() { asm volatile("nop" ::: "memory"); }
Это довольно тонко, но эффективно сообщает компилятору (gcc), что он не может избавиться от этого фрагмента непрозрачного asm и что непрозрачный asm может читать или записывать любую глобально видимую часть памяти. Это эффективно не позволяет компилятору переупорядочивать загрузки/сохранения через эту границу.
Для вашего примера:
memory_barrier(); в то время как (число == 0) { memory_barrier(); ... }
Теперь чтение num застряло на месте. И потенциально, что более важно, он застрял на месте по отношению к другому коду. Итак, вы могли бы:
while (flag == 0) { memory_barrier(); } // spin
process data[0..N]
И другой поток делает:
populate data[0..N]
memory_barrier();
flag = 1;
PS. Если вы делаете такие вещи (по сути, создаете свои собственные примитивы синхронизации), выигрыш в производительности может быть большим, но риск качества высок. Jinx особенно хорошо находит ошибки в этих незаблокированных структурах. Поэтому вы можете использовать его или какой-либо другой инструмент для проверки этого материала.
ППС. В сообществе linux есть хороший пост об этом под названием «летучие данные считаются вредными», проверьте его.
person
Dave Dunn
schedule
02.10.2010