#c #multithreading #concurrency #stdatomic
#c #многопоточность #параллелизм #stdatomic
Вопрос:
Я пытаюсь понять порядок памяти, введенный atomic_exchange[_explicit]
и написанный следующим кодом:
static _Atomic int i = 123;
void *update(void *ignored){
if(atomic_exchange_explicit(amp;i, 200, memory_order_release) != 200){ //1
printf("Updatedn", stdout);
}
}
int main(int args, const char *argv[]){
pthread_t t1;
pthread_create(amp;t1, NULL, amp;update, NULL);
pthread_t t2;
pthread_create(amp;t2, NULL, amp;update, NULL);
sleep(1000);
}
Вопрос: Возможно Updatedn
ли, что он будет напечатан дважды (обоими потоками)?
Я думаю, что поведение не определено. UB сохраняется, даже если мы заменим memory_order_release
на memory_order_acquire
at //1
. Сгенерированный код тот же для acq / rel / acq_rel: https://godbolt.org/z/sFjcve .
Это связано с тем, что у нас есть гонка данных, поскольку для удержания синхронизации с отношением нам нужно, чтобы одна операция была acquire
операцией, а следующая операция — release
операцией, а операция освобождения считывает значение, записанное побочным эффектом, из последовательности освобождения операции получения 5.1.2.4(p11)
:
В частности, атомарная операция A, которая выполняет операцию освобождения объекта M, синхронизируется с атомарной операцией B, которая выполняет операцию получения над M и считывает значение, записанное любым побочным эффектом в последовательности освобождения, возглавляемой A.
Таким образом, единственный способ сделать поведение этого кода четко определенным — заменить atomic_exchange_explicit(amp;i, 200, memory_order_release) != 200
на atomic_exchange(amp;i, 200) != 200
Ответ №1:
Вы ошибаетесь. Независимо от запрошенного порядка памяти, обмен является атомарным. Порядок памяти объясняет, как эта операция чтения, записи или чтения-изменения-записи взаимодействует с другими операциями, но операция всегда атомарна.
Комментарии:
1. Я не заметил
7.17.3(p12)
: атомарные операции чтения-изменения-записи всегда должны считывать последнее значение (в порядке изменения), сохраненное перед записью, связанной с операцией чтения-изменения-записи .. Так что, кажется, я вполне могу указать evenmemory_order_relaxed
, и это не приведет к гонке данных, правильно?2. Правильно. Порядок памяти определяет, как эта атомарная операция взаимодействует с другими операциями, как объясняют различные упорядочения памяти в их описательных текстах.