Suppose I have two variables:
volatile int a = 0;
int b = 0;
they are shared between two threads. Now in first thread I modify these variables in next order:
a = 1;
b = 2;
in second thread I do:
while (true) {
if (b == 2)
assert(a == 1);
}
Is there a guarantee that second thread never fails? Meaning that second thread reads-out written values of a
and b
in same order that they were written by first thread?
As you can see I made a
volatile and b
non-volatile. So my question is if volatile modifier makes any guarantee on order of memory writes? And if I make b
also volatile
will it improve situation?
Or the only way to guarantee order is to use std::atomic<int>
for both a
and b
?
What about std::mutex
? If I protect both variables by single shared mutex on both threads and use non-volatile variables will it help on memory ordering? I.e. if I do next (both a
and b
are non-volatile):
int a = 0, b = 0; // shared
std::mutex m; // shared
// .... In Thread 1 ....
{
std::unique_lock<std::mutex> l(m);
a = 1; b = 2;
}
// .... In Thread 2 ....
while (true) {
std::unique_lock<std::mutex> l(m);
assert(a == 0 && b == 0 || a == 1 && b == 2);
}
Does above solution of using mutex for non-volatile a
and b
variables guarantee that assertion never fails, meaning that either a
and b
are both 0 or set to correct values 1 and 2 same time? Can it happen sometimes that after releasing mutex a
and b
can be not 1 and 2 for other threads and CPU cores? For example a
writing of a
is delayed then other core sees a
equal to 0 and b
equal to 2, can such happen?
I.e. does mutex guarantee memory order and caches propagation between cores? Maybe acquiring/releasing mutex flushes caches or uses some other memory-ordering-enforsing techniques?
Or I have to use std::atomic
for all shared variables?