简体   繁体   中英

std::condition_variable without a lock

I'm trying to synchonise a set of threads. These threads sleep most of the time, waking up to do their scheduled job. I'm using std::thread for them.

Unfortunately, when I terminate the application threads prevent it from exiting. In C# I can make a thread to be background so that it will be termianted on app exit. It seems to me that equavalint feature is not availabe at C++.

So I decided to use a kind of event indicator, and make the threads to wake up when the app exits. Standard C++11 std::condition_variable requires a unique lock, so I cannot use it, as I need both threads to wake up at the same time (they do not share any resources).

Eventually, I decided to use WinApi's CreateEvent + SetEvent + WaitForSingleObject in order to solve the issue.

I there a way to achieve the same behavior using just c++11?

Again, what do I want:

  1. a set of threads are working independently and usually are asleep for a particular period (could be different for different threads;
  2. all threds check a variable that is availabe for all of them whether it is a time to stop working (I call this variable IsAliva ). Actually all threads are spinning in loop like this:

     while (IsAlive) { // Do work std::this_thread::sleep_for(...); } 
  3. threads must be able to work simultaneously, not blocking each other;
  4. when the app is closed and event is risen and it makes the thread to wake up right now, no matter the timeout;
  5. waken up, it checks the IsAlive and exits.

yes you can do this using standard c++ mechanisms of condition variables, a mutex and a flag of somekind

// Your class or global variables
std::mutex deathLock;
std::condition_variable deathCv;
bool deathTriggered = false;

// Kill Thread runs this code to kill all other threads:
{
    std::lock_guard<std::mutex> lock(deathLock);
    deathTriggered = true;
}
deathCv.notify_all();

// You Worker Threads run this code:
while(true)
{
   ... do work

   // Now wait for 1000 milliseconds or until death is triggered:
   std::unique_lock<std::mutex> lock(deathLock);
   deathCv.wait_for(lock, std::chrono::milliseconds(1000), [](){return deathTriggered;});

   // Check for death
   if(deathTriggered)
   {
      break;
   }
}

Note that this runs correctly in the face of death being triggered before entering the condition. You could also use the return value from wait_for but this way is easier to read imo. Also, whilst its not clear, multiple threads sleeping is fine as the wait_for code internally unlocks the unique_lock whilst sleeping and reacquires it to check the condition and also when it returns.

Finally, all the threads do wake up 'at the same time' as whilst they're serialised in checking the bool flag, this is only for a few instructions then they unlock the lock as they break out of the loop. It would be unnoticeable.

在c ++ 11中,您应该能够detach()线程,以便将其视为守护程序线程,这意味着如果应用程序终止,该线程将自动停止。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM