Search code examples
c++multithreadingboost-thread

Boost synchronization


I have NUM_THREADS threads, with the following codes in my thread:

/*
Calculate some_value;
*/

//Critical section to accummulate all thresholds
{
    boost::mutex::scoped_lock lock(write_mutex);
    T += some_value;
    num_threads++;
    if (num_threads == NUM_THREADS){
        T = T/NUM_THREADS;
        READY = true;
        cond.notify_all();
        num_threads = 0;
    }
}

//Wait for average threshold to be ready
if (!READY)
{
    boost::unique_lock<boost::mutex> lock(wait_mutex);
    while (!READY){
        cond.wait(lock);
    }
}
//End critical section

/*
do_something;
*/

Basically, I want all the threads to wait for the READY signal before continuing. num_thread is set to 0, and READY is false before threads are created. Once in a while, deadlock occurs. Can anyone help please? All the boost variables are globally declared as follows:

boost::mutex write_mutex;
boost::mutex wait_mutex;
boost::condition cond;

Solution

  • The code has a race condition on the READY flag (which I assume is just a bool variable). What may happen (i.e. one possible variant of thread execution interleaving) is:

    Thread T1:                                 Thread T2:
    if (!READY)                                
    {
        unique_lock<mutex> lock(wait_mutex);   mutex::scoped_lock lock(write_mutex);
        while (!READY)                         /* ... */
        {                                      READY = true;
            /* !!! */                          cond.notify_all();
            cond.wait(lock);
        }
    }
    

    The code testing the READY flag is not synchronized with the code setting it (note the locks are different for these critical sections). And when T1 is in a "hole" between the flag test and waiting at cond, T2 may set the flag and send a signal to cond which T1 may miss.

    The simplest solution is to lock the right mutex for the update of READY and condition notification:

    /*...*/
    T = T/NUM_THREADS;
    {
        boost::mutex::scoped_lock lock(wait_mutex);
        READY = true;
        cond.notify_all();
    }