Порядок памяти, представленный atomic_exchange_explicit / atomic_exchange - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь понять порядок памяти, вызванный atomic_exchange[_explicit], и написал следующий код:

static _Atomic int i = 123;

void *update(void *ignored){
    if(atomic_exchange_explicit(&i, 200, memory_order_release) != 200){ //1
        printf("Updated\n", stdout);
    } 
}

int main(int args, const char *argv[]){
    pthread_t t1;
    pthread_create(&t1, NULL, &update, NULL);

    pthread_t t2;
    pthread_create(&t2, NULL, &update, NULL);

    sleep(1000);
}

Вопрос : Возможно ли, что Updated\n будет напечатан дважды (обеими нитями)?

Я думаю поведение не определено . UB удерживается, даже если мы заменим memory_order_release на memory_order_acquire в //1. Сгенерированный код такой же для acq / rel / acq_rel: https://godbolt.org/z/sFjcve.

Это потому, что у нас гонка данных, так как для синхронизации с отношением, которое необходимо удерживать, нам нужна одна операция - операция acquire, а следующая операция - операция release, а операция освобождения считывает значение, записанное побочным эффектом. из последовательности разблокирования операции получения 5.1.2.4(p11):

В частности, атомарная операция A, которая выполняет операцию освобождения на объекте M синхронизируется с атомарной операцией B, которая выполняет операция получения на M и читает значение, записанное любым побочным эффектом в последовательности выпуска, возглавляемой А.

Таким образом, единственный способ сделать поведение этого кода четким - заменить atomic_exchange_explicit(&i, 200, memory_order_release) != 200 на atomic_exchange(&i, 200) != 200

1 Ответ

4 голосов
/ 17 апреля 2019

Вы не правы.Независимо от запрошенного порядка памяти обмен является атомарным.Упорядочение памяти объясняет, как эта операция чтения, записи или чтения-изменения-записи взаимодействует с другими операциями, но операция всегда атомарная.

...