condition_variable wait_for 在 C++ 中
condition_variable wait_for in C++
我在 Visual studio 2019 年与 condition_variable
合作。condition_variable.wait_for()
函数 returns std::cv_status::no_timeout
没有任何通知。
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::condition_variable cv;
std::mutex mtx;
bool called = false;
void printThread()
{
std::unique_lock<std::mutex> lck(mtx);
while (std::cv_status::timeout == cv.wait_for(lck, std::chrono::seconds(1)))
{
std::cout << "*";
}
std::cout << "thread exits" << std::endl;
}
int main()
{
std::thread th(printThread);
th.join();
std::cout << "program exits" << std::endl;
}
我认为代码永远不会退出并继续打印 *
,但它会在打印一些 *
后退出。
这是输出:
********************************************************************thread exits
program exits
为什么会这样?难道就是所谓的“spurious wakeups”?
是的,这是“虚假唤醒”。这在 cppreference.com's reference page for wait_for
:
上有解释
It may also be unblocked spuriously. When unblocked, regardless of the
reason, lock is reacquired and wait_for() exits.
翻译:您的计算机中有 gremlins。他们偶尔会脾气暴躁。如果他们确实变得脾气暴躁,则在请求的超时到期前 wait_for
returns。当这种情况发生时:
Return value
- std::cv_status::timeout if the relative timeout specified by
rel_time expired, std::cv_status::no_timeout otherwise.
这似乎正是您所看到的。 C++ 标准允许 C++ 实现从 wait_for
过早地 return,出于任意原因,除非你 do return从wait_for
超时时,no_timeout
就是你得到的。
您可能想知道为什么 wait_for
(以及其他几个类似的函数)可能会决定放弃他们的手并 return “虚假地”。但那将是一个不同的问题...
如前所述,它正在醒来 spurious wakeup
。这样的事情使功能 wait_for
完全无用。解决方法是在进入等待循环之前使用wait_until
保存当前时间:
int count = 1;
std::mutex mutex;
std::condition_variable condition_variable;
void wait() {
std::unique_lock<std::mutex> lock(mutex);
count--;
int timeout = 1000; // 1 second
std::chrono::time_point<std::chrono::system_clock> timenow =
std::chrono::system_clock::now();
while(count < 0) {
std::cv_status status = condition_variable.wait_until(
lock,
timenow + std::chrono::duration<double,std::ratio<1,1000>>(timeout));
if ( std::cv_status::timeout == status) {
count++;
break;
}
}
}
我在 Visual studio 2019 年与 condition_variable
合作。condition_variable.wait_for()
函数 returns std::cv_status::no_timeout
没有任何通知。
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::condition_variable cv;
std::mutex mtx;
bool called = false;
void printThread()
{
std::unique_lock<std::mutex> lck(mtx);
while (std::cv_status::timeout == cv.wait_for(lck, std::chrono::seconds(1)))
{
std::cout << "*";
}
std::cout << "thread exits" << std::endl;
}
int main()
{
std::thread th(printThread);
th.join();
std::cout << "program exits" << std::endl;
}
我认为代码永远不会退出并继续打印 *
,但它会在打印一些 *
后退出。
这是输出:
********************************************************************thread exits
program exits
为什么会这样?难道就是所谓的“spurious wakeups”?
是的,这是“虚假唤醒”。这在 cppreference.com's reference page for wait_for
:
It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait_for() exits.
翻译:您的计算机中有 gremlins。他们偶尔会脾气暴躁。如果他们确实变得脾气暴躁,则在请求的超时到期前 wait_for
returns。当这种情况发生时:
Return value
- std::cv_status::timeout if the relative timeout specified by rel_time expired, std::cv_status::no_timeout otherwise.
这似乎正是您所看到的。 C++ 标准允许 C++ 实现从 wait_for
过早地 return,出于任意原因,除非你 do return从wait_for
超时时,no_timeout
就是你得到的。
您可能想知道为什么 wait_for
(以及其他几个类似的函数)可能会决定放弃他们的手并 return “虚假地”。但那将是一个不同的问题...
如前所述,它正在醒来 spurious wakeup
。这样的事情使功能 wait_for
完全无用。解决方法是在进入等待循环之前使用wait_until
保存当前时间:
int count = 1;
std::mutex mutex;
std::condition_variable condition_variable;
void wait() {
std::unique_lock<std::mutex> lock(mutex);
count--;
int timeout = 1000; // 1 second
std::chrono::time_point<std::chrono::system_clock> timenow =
std::chrono::system_clock::now();
while(count < 0) {
std::cv_status status = condition_variable.wait_until(
lock,
timenow + std::chrono::duration<double,std::ratio<1,1000>>(timeout));
if ( std::cv_status::timeout == status) {
count++;
break;
}
}
}