我正在尝试使用条件变量来触发第二个线程在一定数量的缓冲区位于双端队列后执行一些工作。
- main() 正在紧凑且时间敏感的循环中读取 ADC 数据
- main() 将缓冲区添加到双端队列(由线程池处理 经理)
- 双端队列深度是可变的,因此在 main() 中测试深度 >= 4 和 那么调用 notify_one 是不可能的(即:在繁重的处理过程中 次,双端队列的深度可能多达 200 或 300 个缓冲区 或在光处理过程中少至 4 个)
- thrd() 永远不需要向 main() 发出信号
我的问题是,在 thrd() 中,在获得信号和缓冲区 < 4 后,它循环返回 while 循环并立即再次获得条件。有没有办法重置简历?
deque<int> vbufs;
std::mutex thrdLock;
void thrd()
{
while (true) {
cout << "thrd() waiting for lock\n";
std::unique_lock < std::mutex > lock(thrdLock);
cout << "thrd() waiting for condition\n";
cv.wait(lock, []{ return (vbufs.size() > 0); });
thrdLock.unlock();
cout << "thrd() condition set\n";
if (vbufs.size() >= 4) { // pretend to do something with 4 buffers and remove them
std::lock_guard < std::mutex > lock(thrdLock);
vbufs.pop_front();
vbufs.pop_front();
vbufs.pop_front();
vbufs.pop_front();
cout << "thrd() reducing buffers:" << vbufs.size() << endl;
}
}
}
int main(int argc, char* argv[]) {
std::thread t1(thrd);
int tctr = 0;
while (true) {
usleep(1000);
{
cout << "main() waiting for lock\n";
std::lock_guard < std::mutex > lock(thrdLock);
vbufs.push_back(++tctr);
cout << "main() incremented buffers:" << vbufs.size() << endl;
}
cv.notify_one();
}
return 0;
}
最佳答案
您不能重置条件变量;这没有任何意义——通知它不会改变它的状态,所以没有什么可以重置的。当它被通知时,只有一个已经在等待的线程可以被唤醒。如果该线程然后再次等待,它将不会继续,直到条件变量被重新通知。
如果你只想在有四个或更多缓冲区时工作,你不应该这样改变你的等待吗?
cv.wait(lock, []{ return (vbufs.size() >= 4); });
更重要的是,您可能同时从两个不同的线程读取和写入 vbufs
- 您的 if (vbufs.size() >= 4)
发生在外部锁定,因此可以在调用 push_back
的同时发生。这会导致未定义的行为,这可能会解释您所看到的。
关于c++ - 如何重置 std::condition_variable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35139722/