In a multithreaded C++ program, I have the equivalent of this running in one thread:
while(obj->member) { } // waiting for obj->member to be set to false in another thread
and in another thread, obj->member is set to false. Even when it's set to false, however, the loop doesn't break. If I change it to this:
while(obj->member) { Sleep(1) }
It works as expected and breaks when obj->member is set to false in the other thread.
Why does it work like this?
Try making member volatile
. This will force it to be fetched from memory each time it is used, rather than from a CPU register (which is how the compiler might optimise it.)
Obj
must be declared volatile
. That tells the compiler that it's value may change by some other thread.
When you add the Sleep
, the compiler knows other threads are at work, and assumes that it might change.
The fact that it works is mostly accidental. If you want to do things like this dependably, you just about need to use some sort of OS-supplied IPC mechanism, possibly with Boost Interprocess (e.g., mutex or semaphore) to give a more portable front end.
volatile
, while often put forward as a solution to problems like this, is neither necessary nor sufficient. It can hurt performance (a lot) but still isn't enough to make threading work correctly. If you're programing for .NET, Microsoft has defined its version of volatile
to provide (at least some degree of) thread safety. Otherwise (in real C or C++), it's of little real use, and can cause considerable harm.
I should also mention that this is a long ways from the first time this mistake has been made. Way back when, no less an authority than Andre Alexandrescu wrote a fairly substantial article in Doctor Dobbs about using volatile
for threading. He's since realized that he was wrong, but (to a large extent) the damage was done -- especially since volatile
is oh so very close to doing the right things that it's extremely easy to mistake it for being right/useful in threading.
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