Boost logo

Boost Users :

Subject: [Boost-users] [thread] memory synchronization multiple mutexes
From: firespot (firespot71_at_[hidden])
Date: 2014-08-28 08:53:18


Hi,

How does memory synchronization and visibility behave when multiple
mutexes are involved?
I have two groups of threads (boost::thread_group) and two mutexes
(boost::mutex m1, boost::mutex m2) + associated condition variables,
with each thread group being responsible to write to some variables
(here Ptr, run) and consistently using "its" mutex for locking.
However there is a piece of code that looks - much simplified - like this:

void f()
{
   {
     boost::unique_lock<boost::mutex> Lock(m1);
       Ptr = someAddress; // set the Ptr from 0 to some memory address
   }

   {
     boost::unique_lock<boost::mutex> Lock(m2);
     run = 1; // was 0, inform that execution can proceed
     condVar2.notify_all();
   }

    ...

    // wait until Ptr has been reset to 0
    {
     boost::unique_lock<boost::mutex> Lock(m1);
     while (Ptr != 0)
       condVar1.wait(Lock);
   }
}

and another function:

void g()
{
   {
     boost::unique_lock<boost::mutex> Lock(m2);
     while (run == 0)
       condVar2.wait(Lock);
   }

   // run the execution, e.g.
   std::copy(Ptr, Ptr + 100, Target);

    // finally all finished, signal back that Ptr is not needed any more
   {
     boost::unique_lock<boost::mutex> Lock(m1);
       Ptr = 0;
     condVar1.notify_all();
   }
}

f() is only invoked from a thread of the first group, and g() only from
a thread of the second group. Whenever Ptr might get changes the first
mutex (m1) and its associated condition-variable is used, and whenver
run might get changed the second mutex and its associated conditional
variable is used. The control flow guarantees that run is not set to 1
prior to Ptr being set, and thus in g() the "running" itself (here the
std::copy) cannot commence earlier. However, what puzzles me now: I used
a different mutex for setting Ptr and setting/checking run. Does this
have any impact whatsoever on memory visibility across the threads in
the two thread-groups? Specifically, is it always guaranteed that when
g() continues its execution (because run == 1) that it must see the
correct value of Ptr (a non-NULL value)? Or is it possible that it still
sees 0 and I'd have to make a separate locking involving m1 to guarantee
a proper read for Ptr as anything written under a lock of m1 is also
only guaranteed to be later properly read if the locking also used m1?

thanks!


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net