您可以通过以下任何一种方式进行编码:
- 使用原子和轮询循环。
- 使用
condition_variable
.
我已经在下面为您编码了两种方式。在我的系统上,我可以实时监控任何给定进程正在使用多少 CPU。
首先是轮询循环:
#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 秒来执行,而在执行过程中需要大约 99.6% 的 cpu。
或者使用condition_variable
:
#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。如果您正在编写一个可以在电池供电的设备上执行的应用程序,那么后者在电池上几乎是无限容易的。
现在诚然,如果您的 实现非常糟糕std::condition_variable
,它可能与轮询循环一样低效。然而在实践中,这样的供应商应该很快就会倒闭。
更新
为了咧嘴笑,我用一个虚假的唤醒检测器增加了我的 condition_variable 等待循环。我再次运行它,它没有打印出任何东西。没有一个虚假的唤醒。这当然不能保证。但它确实证明了高质量的实施可以实现什么。