On 25.07.15 20.58, Doug Mika wrote:
> #include <iostream>
> #include <thread>
> #include <functional>
> #include <mutex>
> #include <condition_variable>
> #include <chrono>
>
> using namespace std;
>
> void functionOne();
> void functionTwo();
>
> mutex mtx;
> condition_variable cvOne, cvTwo;
> long t1Value=1, t2Value=2, sum=0;
> bool t1Ready=false, t2Ready=false;
>
> int main()
> {
> cout<<"Solution: "<<endl;
> thread t1(functionOne);
> thread t2(functionTwo);
> //cout<<"main thread going to sleep"<<endl;
> while (!t1Ready||!t2Ready) {
> cout<<"."; //IF YOU DELETE THIS cout, THE PROGRAM DOESN'T WORK!!
Indeed. Your booleans are not declared to be changed asynchronously. So
the compiler may optimize away the entire loop and check the condition
only once. And even if the compiler will not do this kind of
optimization you are missing a memory barrier, i.e. the CPU cache of the
executing thread might return out-dated values.
This changes by the call to cout<<. First of all any function call might
change any static variable unless it is an inline function and the
compiler knows its code. So calling a function from another object
module implicitly acts like volatile here.
Secondly the iostreams are thread-safe (nowadays guaranteed), i.e.
writing to the same stream from different threads is defined behavior in
the way that it will not turn the stream into an inconsistent state and
no output is lost. (Note that the order of the output is still undefined.)
However, this thread safety is usually implemented by a mutex. So each
call to operator<< acquires and releases a mutex at least once. The
mutex operations in turn imply a full memory barrier. So the CPU cache
is also synchronized. That't the reason why it works.
This is also why others recommended atomic_bool.
volatile in contrast is /not sufficient/ as it solves the optimization
problem but not the memory fence for cache coherence. Although on
typical hardware the caches become synchronized somewhat later. So your
detection is usually only delayed undefinedly.
But besides all the discussion above I would reject this code as soon as
I see it anywhere because of the busy loop that constantly eats CPU
cycles without any reasonable result. A wait() is missing in this loop.
I would not even accept this for educational purposes unless the task is
to demonstrate what happens because of the wrong code.
Marcel