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?