In a talk about concurrency and the C++11 memory model Herb Sutter gives examples of illegal optimizations.
http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2
From the slide at minute 17:
void f(vector<widget>& v) {
if(v.length()>0) xMutex.lock();
for(int i = 0; i < v.length(); ++i)
++x; // write is conditional
if(v.length()>0) xMutex.unlock();
}
"A very likely (if deeply flawed) transformation of the central loop:"
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1; // oops: write is not conditional
x = r1;
He explains, "...this write is not conditional, it will happen on every execution even if doOptionalWork is false, which will inject a write that is not protected by the mutex lock, that injects a race..."
Why does he say the invented write is not protected by the mutex lock? I understood the full transformation being described as the following.
// "optimized" version 1
void f(vector<widget>& v) {
if(v.length() > 0) xMutex.lock()
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1;
x = r1;
if(v.length() > 0) xMutex.unlock();
}
But it could also be this.
// "optimized" version 2
void f(vector<widget>& v) {
if(v.length() > 0) xMutex.lock()
r1 = x;
for(int i = 0; i < v.length(); ++i)
++r1;
if(v.length() > 0) xMutex.unlock();
x = r1;
}
Clearly version 2 isn't thread safe but I'm not sure about version 1. Is version 1 thread safe? What if there are no other lines that write to x in play?
Just now I began typing "Either v.length() is 0 or it isn't..." and realized that even tautologies fail me in a multithreaded world. I don't know where I can begin reasoning about this.
The mutex is only used if there is something inside of the vector. Running this method concurrently on two empty vectors results in a data race because we don't lock at all, yet we write to x.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With