Как проверить поведение std :: memory_order_relaxed? - PullRequest
0 голосов
/ 06 сентября 2018

Я прочитал документ std :: memory_order_relaxed .

Одна часть объяснения Расслабленный заказ - это ....

// Thread 1:
r1 = y.load(memory_order_relaxed); // A
x.store(r1, memory_order_relaxed); // B
// Thread 2:
r2 = x.load(memory_order_relaxed); // C 
y.store(42, memory_order_relaxed); // D

и объяснение этому сказано ...

[Это] разрешено производить r1 == r2 == 42. В частности, это может произойти, если D завершается до C в потоке 2, либо из-за переупорядочения компилятора, либо во время выполнения.

Я понял объяснение и попробую проверить на своем компьютере следующий код:

std::atomic<int> x = {0};
std::atomic<int> y = {0};

int r1, r2;

void task1() {
    // Thread 1:
    r1 = y.load(memory_order_relaxed); // A
    x.store(r1, memory_order_relaxed); // B
}

void task2() {
   // Thread 2:
    r2 = x.load(memory_order_relaxed); // C 
    y.store(42, memory_order_relaxed); // D
}


int main()
{
    std::thread t2 (task2);
    std::thread t1 (task1);

    t1.join();
    t2.join();

    cout << "r1: " << r1
        << "\nr2: " << r2 << endl;

    return 0;
}

Результаты этого кода никогда r1 == r2 == 42, что говорит о возможном поведении в этом документе.

Что-то не так в этом коде? Или есть какое-то недоразумение?

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Ваш код немного наивен, потому что к моменту запуска 2-го потока 1-й может закончиться. Потоки должны выполнять эти фрагменты кода действительно одновременно.

Чтобы значение r1 == r2 == 42 было истинным, требуется, чтобы нагрузка C переупорядочивалась после магазина D, x86 не выполняет переупорядочения нагрузок после магазинов в настоящее время, так что вы можете никогда не наблюдать такого рода переупорядочение на этой платформе (если компилятор не переупорядочивает C с D).

ARM и PowerPC, с другой стороны, имеют более слабые модели памяти. См. Упорядочение памяти во время выполнения Таблица.

0 голосов
/ 06 сентября 2018

Или есть недоразумение?

Да, есть. std::memory_order_relaxed позволяет в вашей программе реализовать реализацию (компилятор), нацеленную на архитектуру, чтобы создать программу, которая может наблюдать побочный эффект r1 == r2 == 42.

Реализация не должна создавать такую ​​программу, и такая программа не должна вызывать такой побочный эффект; в любом случае это возможный исход.

Как проверить поведение std :: memory_order_relaxed?

Я не вижу общего решения этого вопроса. Вы можете только проверить, что побочный эффект you соответствует совпадениям со спецификациями std::memory_order_relaxed.

...