为什么我需要std :: condition_variable? [英] why do I need std::condition_variable?
问题描述
我发现 std :: condition_variable
由于虚假唤醒而很难使用。因此有时候我需要设置一个标志,例如:
I found that std::condition_variable
is very difficult to use due to spurious wakeups. So sometimes I need to set a flags such as:
atomic<bool> is_ready;
我将 is_ready
设置为 true
在我打电话通知之前( notify_one()
或 notify_all()
),然后我等待:
I set is_ready
to true
before I call notify (notify_one()
or notify_all()
), and then I wait:
some_condition_variable.wait(some_unique_lock, [&is_ready]{
return bool(is_ready);
});
是否有任何我不应该这样做的理由:(编辑:好,这真的
Is there any reason that I shouldn't just do this: ( Ok, this is really a bad idea.)
while(!is_ready) {
this_thread::wait_for(some_duration); //Edit: changed from this_thread::yield();
}
如果 condition_variable
选择了等待时间(我不知道这是否成立),我宁愿自己选择。
And if condition_variable
had chosen a waiting duration (I don't know whether this is true or not), I prefer choose it myself.
推荐答案
您可以使用以下任何一种方式进行编码:
You can code this either way:
- 使用原子和轮询循环。
- 使用
condition_variable
。
- Using atomics and a polling loop.
- Using a
condition_variable
.
我在下面为您两种方式都进行了编码。在我的系统上,我可以实时监视任何给定进程使用了多少cpu。
I've coded it both ways for you below. On my system I can monitor in real time how much cpu any given process is using.
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
std::atomic<bool> is_ready(false);
void
test()
{
std::this_thread::sleep_for(std::chrono::seconds(30));
is_ready.store(true);
}
int
main()
{
std::thread t(test);
while (!is_ready.load())
std::this_thread::yield();
t.join();
}
对我来说这需要30秒才能执行,而执行该过程大约需要30秒cpu的99.6%。
For me this takes 30 seconds to execute, and while executing the process takes about 99.6% of a cpu.
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
bool is_ready(false);
std::mutex m;
std::condition_variable cv;
void
test()
{
std::this_thread::sleep_for(std::chrono::seconds(30));
std::unique_lock<std::mutex> lk(m);
is_ready = true;
cv.notify_one();
}
int
main()
{
std::thread t(test);
std::unique_lock<std::mutex> lk(m);
while (!is_ready)
{
cv.wait(lk);
if (!is_ready)
std::cout << "Spurious wake up!\n";
}
t.join();
}
除了在30秒执行期间,该过程具有完全相同的行为占用了0.0%的CPU。如果您要编写一个可以在电池供电的设备上执行的应用程序,那么后者在电池上的使用几乎是无限的。
This has the exact same behavior except that during the 30 second execution, the process is taking 0.0% cpu. If you're writing an app that might execute on a battery powered device, the latter is nearly infinitely easier on the battery.
现在可以肯定的是,如果您的设备很差, std :: condition_variable
的实现,其效率可能与轮询循环相同。但是实际上,这样的供应商应该很快倒闭。
Now admittedly, if you had a very poor implementation of std::condition_variable
, it could have the same inefficiency as the polling loop. However in practice such a vendor ought to go out of business fairly quickly.
更新
对于咧嘴笑,我用一个伪造的唤醒检测器增强了condition_variable等待循环。我再次运行它,它没有打印出任何内容。没有一个虚假的唤醒。当然不能保证。但这确实证明了质量实现可以实现的目标。
For grins I augmented my condition_variable wait loop with a spurious wakeup detector. I ran it again, and it did not print out anything. Not one spurious wakeup. That is of course not guaranteed. But it does demonstrate what a quality implementation can achieve.
这篇关于为什么我需要std :: condition_variable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!