C++ mutex doesn't work - synchronization fails
Why does everyone learning this stuff for the first time assume the tried-and-tested synchronization primitives that work for everyone else are broken, and not their assumptions?
The mutex is fine. Your mental model is broken. This should be your starting assumption.
I expect that:
- sum is always equal to 300
That would be the case if you join
ed both threads before checking the value. But you haven't done that, so you're doing an entirely un-sychronized read of sum
while two other threads are possibly mutating it. This is a data race. A mutex doesn't protect your data unless you always use the mutex when accessing the data.
Let's say we make the minimal change so sum
is always protected:
thread t1(addValue, 100); // a
thread t2(addValue, 200); // b
m.lock();
if (sum == 300) // c
{
counter1++;
}
else
{
counter2++;
}
sum = 0;
m.unlock();
now some of the available orderings are:
- abc - what you expected (and what would be guaranteed if you joined both threads before reading
sum
)
- acb - you read
100
at line c
, increment counter2
, and the second thread increments sum
to 300
after you read it (but you never see this)
- cab - you read
0
immediately, before the two threads have even been scheduled to run
- bca - you read
200
, it's later incremented to 300
after you checked
- etc. - every permutation is permitted, unless you make some effort to explicitly order them
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…