Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test the behavior of std::memory_order_relaxed?

I have read the doc of std::memory_order_relaxed.

One part of explanation of Relaxed ordering is ....

// 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

and the explanation of this is said ...

[It] is allowed to produce r1 == r2 == 42. In particular, this may occur if D is completed before C in thread 2, either due to compiler reordering or at runtime.

I have understood the explanation, and try to test on my computer as following code:

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;
}

The results of this code is never r1 == r2 == 42, which is said that it's a possible behavior in that doc.

Is there any wrong in this code? Or, is there any misunderstanding?

like image 249
sheucm Avatar asked Sep 06 '18 08:09

sheucm


2 Answers

Or, is there any misunderstanding?

Yes there is one. What std::memory_order_relaxed allows in your program is for an implementation (a compiler) targeting an architecture, to produce a program which may observe the side effect r1 == r2 == 42.

An implementation does not have to produce such a program, and such a program does not have to produce that side effect; it is a possible outcome anyway.

How to test the behavior of std::memory_order_relaxed?

I cannot see a general solution to this question. You can only check that the side effect you observes matches with the specs of std::memory_order_relaxed.

like image 142
YSC Avatar answered Nov 20 '22 04:11

YSC


Your code is a bit naive because by the time the 2nd thread starts the 1st one may have completed. The threads need to run these pieces of code truly concurrently.

For r1 == r2 == 42 to be true it requires load C to be reordered past store D, x86 does not do loads reordered after stores currently, so that you may never observe this kind of reordering on this platform (unless the compiler reorders C with D).

ARM and PowerPC, on the other hand, have weaker memory models. See Runtime memory ordering table.

like image 21
Maxim Egorushkin Avatar answered Nov 20 '22 02:11

Maxim Egorushkin