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 实现相同的行为吗?
再说一次,我想要什么:
- 一组线程独立工作,通常处于休眠状态
对于特定时期(不同线程可能不同;
all threds 检查一个对他们所有人都可用的变量是否
是时候停止工作了(我称这个变量为IsAliva
)。
实际上所有线程都像这样循环旋转:
while (IsAlive) {
// Do work
std::this_thread::sleep_for(...);
}
- 线程必须能够同时工作,不能相互阻塞;
- 当应用程序关闭并且事件发生并且它使线程
现在醒来,不管超时;
- 醒来,它检查
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 标志时被序列化时,这仅用于几条指令,然后它们在跳出循环时解锁锁。不会引起注意。
我正在尝试同步一组线程。这些线程大部分时间都在休眠,醒来后执行它们预定的工作。我正在为他们使用 std::thread
。
不幸的是,当我终止应用程序线程时阻止它退出。在 C# 中,我可以将一个线程设置为 background
,这样它将在应用程序退出时终止。在我看来,equavalint 功能在 C++ 中不可用。
所以我决定使用一种事件指示器,让线程在应用程序退出时唤醒。标准 C++11 std::condition_variable
需要唯一锁,所以我不能使用它,因为我需要两个线程同时唤醒(它们不共享任何资源)。
最终,我决定使用 WinApi 的 CreateEvent
+ SetEvent
+WaitForSingleObject
来解决问题。
我有办法只使用 c++11 实现相同的行为吗?
再说一次,我想要什么:
- 一组线程独立工作,通常处于休眠状态 对于特定时期(不同线程可能不同;
all threds 检查一个对他们所有人都可用的变量是否 是时候停止工作了(我称这个变量为
IsAliva
)。 实际上所有线程都像这样循环旋转:while (IsAlive) { // Do work std::this_thread::sleep_for(...); }
- 线程必须能够同时工作,不能相互阻塞;
- 当应用程序关闭并且事件发生并且它使线程 现在醒来,不管超时;
- 醒来,它检查
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 标志时被序列化时,这仅用于几条指令,然后它们在跳出循环时解锁锁。不会引起注意。