Чтобы ваш код всегда работал на слабо упорядоченных архитектурах, вы должны установить MemoryBarrier перед тем, как писать s_Initialized.
s_Provider = new MemershipProvider;
// MUST PUT BARRIER HERE to make sure the memory writes from the assignment
// and the constructor have been wriitten to memory
// BEFORE the write to s_Initialized!
Thread.MemoryBarrier();
// Now that we've guaranteed that the writes above
// will be globally first, set the flag
s_Initialized = true;
Запись в память, которая происходит в конструкторе MembershipProvider, и запись в s_Provider не гарантируется до того, как вы запишете в s_Initialized на слабо упорядоченном процессоре.
В этой теме много мыслей о том, является ли что-то атомарным или нет. Это не проблема. Проблема в порядке, в котором записи вашего потока видны другим потокам . На слабо упорядоченных архитектурах запись в память происходит не по порядку, и это реальная проблема, а не вхождение переменной в шину данных.
РЕДАКТИРОВАТЬ: На самом деле, я смешиваю платформы в своих заявлениях. В C # спецификация CLR требует, чтобы записи были видны глобально, по порядку (используя дорогие инструкции для каждого магазина, если это необходимо). Следовательно, вам не нужно иметь этот барьер памяти там. Однако, если бы это был C или C ++, где такой гарантии глобального порядка видимости не существует, и ваша целевая платформа может иметь слабо упорядоченную память, и она является многопоточной, то вам нужно убедиться, что записи конструкторов видны глобально, прежде чем обновлять s_Initialized , который тестируется вне замка.