Рассмотрим следующий код, который я нашел на http://preshing.com/20120913/acquire-and-release-semantics/ (но я уверен, что часто встречал его в других местах)
Общий код:
int A = 0;
std::atomic<int> Ready(0);
Код, выполняемый потоком 1:
A = 42
Ready.store(1, std::memory_order_release);
Код, выполняемый потоком 2:
int r1 = Ready.load(std::memory_order_acquire);
int r2 = A;
Тогда можно сказать, что если r1 == 1
, то r2
всегда будет 42 и гонки данных не будет.
Мой первый вопрос: содержит ли код тем не менее гонку данных? Я имею в виду в случае, если r1 == 0
. Например, поток 1 может быть вытеснен на полпути через хранилище к A, а затем поток 2 может продолжить выполнение.
Я бы подумал, что код для Thread 2 следует переписать так:
int r1 = Ready.load(std::memory_order_acquire);
int r2 = 0;
if( r1 == 1 ) {
r2 = A;
}
чтобы избежать потенциальной гонки данных.
Это правда?