Возможно ли (теоретически) для потока выполнить acquire
на одном процессоре, а затем немедленно прервано и возобновлено на другом процессоре, для которого acquire
никогда не выполнялся (и, следовательно, никогда не синхронизировался в соответствии с семантикой получения-выпуска)?
Например рассмотрим следующий код, который использует атомарность C ++ 11 и release-acquire
упорядочение памяти для выполнения безблокировочной поточно-ориентированной инициализации:
if ( false == _initFlag.load(memory_order_acquire) ) {
_foo = ...; // initialize global
_bar = ...; // initialize global
... = ...; // initialize more globals
_initFlag.store(true, memory_order_release);
}
// use the initialized values ...
Если _initFlag.load(memory_order_acquire)
возвращает true, тогда вызывающий поток будет знать, что инициализированные значения _foo
, _bar
и т. д. … видимы (распространяются) на процессор на котором он в данный момент выполняется. Но что делать, если поток сразу же прерывается и перемещается на другой процессор? ..
Гарантирует ли стандарт C ++ 11, что новый процессор будет синхронизирован? Существуют ли какие-либо реализации или архитектуры, которые могут быть уязвимы для этого типа состояния гонки?
Возможно, что он будет выгружен и перенесен на другой процессор после получения, но, насколько мне известно, O / S должен обеспечить сохранение любого явного упорядочения памяти (это, вероятно, то, что он сохраняет в состояние потока). В противном случае было бы очень мало шансов на надежную работу в среде с несколькими процессорами.
Я думаю, что стандарт предполагает, что так и должно быть, на основании этого он должен.
Других решений пока нет …