std::condition_variable 没有锁

std::condition_variable without a lock

我正在尝试同步一组线程。这些线程大部分时间都在休眠,醒来后执行它们预定的工作。我正在为他们使用 std::thread

不幸的是,当我终止应用程序线程时阻止它退出。在 C# 中,我可以将一个线程设置为 background,这样它将在应用程序退出时终止。在我看来,equavalint 功能在 C++ 中不可用。

所以我决定使用一种事件指示器,让线程在应用程序退出时唤醒。标准 C++11 std::condition_variable 需要唯一锁,所以我不能使用它,因为我需要两个线程同时唤醒(它们不共享任何资源)。

最终,我决定使用 WinApi 的 CreateEvent + SetEvent+WaitForSingleObject 来解决问题。

我有办法只使用 c++11 实现相同的行为吗?

再说一次,我想要什么:

  1. 一组线程独立工作,通常处于休眠状态 对于特定时期(不同线程可能不同;
  2. all threds 检查一个对他们所有人都可用的变量是否 是时候停止工作了(我称这个变量为IsAliva)。 实际上所有线程都像这样循环旋转:

    while (IsAlive) {
      // Do work
      std::this_thread::sleep_for(...);
    }
    
  3. 线程必须能够同时工作,不能相互阻塞;
  4. 当应用程序关闭并且事件发生并且它使线程 现在醒来,不管超时;
  5. 醒来,它检查 IsAlive 并退出。

在c++11中,你应该能够detach()一个线程,这样它就会被当作一个守护线程,这意味着如果应用程序终止,线程会自动停止。

是的,你可以使用条件变量、互斥锁和某种标志的标准 C++ 机制来做到这一点

// 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;
   }
}

请注意,在进入条件之前触发死亡时,这会正确运行。您也可以使用 wait_for 中的 return 值,但这种方式更易于阅读 imo。此外,虽然不清楚,但多线程睡眠很好,因为 wait_for 代码在睡眠时内部解锁 unique_lock 并重新获取它以检查条件以及 returns.

最后,所有线程都唤醒了 'at the same time',因为当它们在检查 bool 标志时被序列化时,这仅用于几条指令,然后它们在跳出循环时解锁锁。不会引起注意。