Yur*_*uri 1 c c++ linux pthreads c++11
这是来自http://www.cplusplus.com/reference/condition_variable/condition_variable/wait_for/的简单代码
如果我用起始线程评论行,为什么wait_for()会立即返回?
像这样:
// condition_variable::wait_for example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <chrono> // std::chrono::seconds
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable, std::cv_status
std::condition_variable cv;
int value;
void read_value() {
std::cin >> value;
cv.notify_one();
}
int main ()
{
std::cout << "Please, enter an integer (I'll be printing dots): ";
//std::thread th (read_value);
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
while (cv.wait_for(lck,std::chrono::seconds(1))==std::cv_status::timeout) {
std::cout << '.';
}
std::cout << "You entered: " << value << '\n';
//th.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更新:
请不要在这个例子中寻找其他问题(相关的缓冲cout ...).最初的问题是为什么跳过wait_for.
简短的回答:编译,-pthread你的问题将消失.
更新:这是libstdc ++中已确认的错误/问题.如果不-pthread作为编译器标志传入,则定时等待调用将立即返回.鉴于该问题的历史(3年),它不太可能很快修复.无论如何,请阅读下面的消息,说明为什么你应该使用带有谓词的条件变量来避免虚假的唤醒问题.即使您使用posix线程库进行链接,它仍然适用.
cplusplus.com上的示例代码有几个问题.对于初学者,修改此行:
std::cout << '.';
Run Code Online (Sandbox Code Playgroud)
这样:
std::cout << '.';
std::cout.flush()
Run Code Online (Sandbox Code Playgroud)
否则,如果没有刷新stdout,你将看不到任何点.
如果您编译您的程序(线程已注释掉),如下所示:
g++ yourcode.cpp -std=c++11
Run Code Online (Sandbox Code Playgroud)
然后生成的a.out程序显示您在未使用该线程时描述的问题.也就是说,当线程未被使用时,会出现虚假的唤醒.这就像在notify()某个未知来源的条件变量上调用了一个幻像调用.这很奇怪,但并非不可能.
但是一旦取消注释了线程变量的声明,程序将因为程序不使用多线程而抛出异常(并崩溃):
terminate called after throwing an instance of 'std::system_error'
what(): Enable multithreading to use std::thread: Operation not permitted
Please, enter an integer (I'll be printing dots): Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
有意思,所以让我们通过重新编译来解决这个问题 -pthread
g++ yourcode.cpp -std=c++11 -pthread
Run Code Online (Sandbox Code Playgroud)
现在,无论是否有线程,一切都按预期工作.似乎没有更多的虚假唤醒.
现在让我们谈谈你为什么看到你所看到的行为. 应始终编写使用条件变量的程序来处理虚假唤醒. 最好使用谓词语句.也就是说,您可能会获得一个幻像通知,导致您的wait或wait_for语句提前返回.来自cplusplus.com的网络上的示例代码不使用谓词,也不处理这种可能性.
我们将其修改如下:
更改此代码块:
while (cv.wait_for(lck,std::chrono::seconds(1))==std::cv_status::timeout) {
std::cout << '.';
}
Run Code Online (Sandbox Code Playgroud)
为此:
while (cv.wait_for(lck,std::chrono::seconds(1), condition_check)==false) {
std::cout << '.';
std::cout.flush();
}
Run Code Online (Sandbox Code Playgroud)
然后在其他地方之外main,但在声明之后value,添加此功能:
bool condition_check() {
return (value != 0);
}
Run Code Online (Sandbox Code Playgroud)
现在等待循环将每秒唤醒和/或当notify输入线程进行调用时.等待循环将继续,直到value != 0.(从技术上讲,value应该在线程之间进行同步,使用锁或作为std :: atomic值,但这是一个小细节).
现在的谜团是为什么非谓词版本wait_for遭受虚假的wake_up问题.我的猜测是单线程C++运行时的问题在使用多线程运行时(-pthread)时会消失.condition_variable当链接posix线程库时,可能有不同的行为或不同的实现.
| 归档时间: |
|
| 查看次数: |
1864 次 |
| 最近记录: |