等待中的谓词在循环中使用notify时只调用一次
Predicate in wait only called once when using notify in loop
在一个线程的循环中对条件变量调用notify_once
方法时,另一个线程中的wait
方法似乎只检查它一次谓词。示例代码如下所示:
int someNumber = 0;
mutex numberMutex;
condition_variable cv;
void waitFunction()
{
unique_lock<mutex> lock(numberMutex);
auto duration = chrono::seconds(5);
// Predicate is only called once?
cv.wait_for(lock, duration, []() {
cout << "Checking condition: 10 == " << someNumber << 'n';
return someNumber == 10;
});
cout << "Done with this thread...n" << flush;
}
int main()
{
thread waiter(waitFunction);
for (size_t number = 0; number != 50; ++number)
{
{
lock_guard<mutex> guard(numberMutex);
someNumber = number;
}
cv.notify_one();
}
waiter.join();
}
执行此程序会产生以下输出
Checking condition: 10 == 49
Checking condition: 10 == 49
Done with this thread...
而我希望它在每次迭代时检查条件。
这怎么可能?
信号线程不会等待接收到信号。
这意味着在主循环重复并再次递增之前,等待线程可能没有机会唤醒。
您有一个"普通"的竞争条件(虽然不是语言级别的数据竞争,所以没有UB)。
这里有一个反例。根据您平台的速度和日程安排,以下内容:
在Coliru上直播
#include <condition_variable>
#include <iomanip>
#include <iostream>
#include <thread>
using namespace std;
int someNumber = 0;
mutex numberMutex;
condition_variable cv;
void waitFunction() {
unique_lock<mutex> lock(numberMutex);
auto duration = chrono::seconds(5);
// Predicate is only called once?
cv.wait_for(lock, duration, []() {
cout << "Checking condition: 10 == " << someNumber << 'n';
return someNumber == 10;
});
cout << "Done with this thread...n" << flush;
}
int main() {
thread waiter(waitFunction);
for (size_t number = 0; number != 50; ++number) {
this_thread::sleep_for(chrono::milliseconds(1));
{
lock_guard<mutex> guard(numberMutex);
someNumber = number;
std::cout << "notif: " << number << "n";
cv.notify_one();
}
}
waiter.join();
}
可能会打印出类似以下内容:
Checking condition: 10 == 0
notif: 0
Checking condition: 10 == 0
notif: 1
Checking condition: 10 == 1
notif: 2
Checking condition: 10 == 2
notif: 3
Checking condition: 10 == 3
notif: 4
Checking condition: 10 == 4
notif: 5
Checking condition: 10 == 5
notif: 6
Checking condition: 10 == 6
notif: 7
Checking condition: 10 == 7
notif: 8
Checking condition: 10 == 8
notif: 9
Checking condition: 10 == 9
notif: 10
Checking condition: 10 == 10
Done with this thread...
notif: 11
notif: 12
notif: 13
notif: 14
notif: 15
notif: 16
notif: 17
notif: 18
notif: 19
notif: 20
notif: 21
notif: 22
notif: 23
notif: 24
notif: 25
notif: 26
notif: 27
notif: 28
notif: 29
notif: 30
notif: 31
notif: 32
notif: 33
notif: 34
notif: 35
notif: 36
notif: 37
notif: 38
notif: 39
notif: 40
notif: 41
notif: 42
notif: 43
notif: 44
notif: 45
notif: 46
notif: 47
notif: 48
notif: 49
基本原理
如果您需要双向通信,请设置一个标志以向主线程发出返回信号(例如,使用不同的条件变量)
相关文章:
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么 zlib 放气初始化调用一次不起作用?
- 什么是仅调用一次并调用参数的控制台应用
- 谷歌基准测试,如何只调用一次代码?
- Android JNI RegisterNatives:对所有内容调用一次,或者每个函数调用一次
- 系统调用:一次和多次,哪个更好?
- C++菱形问题 - 如何仅调用一次基方法
- 函数被多次执行,同时调用一次
- 只为NOT STATIC类的EACH对象调用一次方法
- 通过调用一次新运算符大容量分配对象
- Boost::asio::async_write,处理程序只调用一次
- 为什么析构函数被调用两次,而构造函数只被调用一次
- 强制子类实现并调用(一次)方法
- 等待中的谓词在循环中使用notify时只调用一次
- boost::future-是否保证wait_callback只被调用一次
- 为什么这个函数只被调用一次
- Qpid质子on_sendable只被调用一次
- 每次选择参数时调用一次的静态变量和函数
- 如何只执行一次方法代码,尽管每帧调用一次
- 在c++中调整vector大小时调用一次类构造函数