两个帖子。主要是不断收集通知,而另一个正在处理其中一些通知。 我实施它的方式 - 不正确,因为我被告知。它造成了什么问题以及它有什么问题?
#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>
#include <chrono>
std::condition_variable foo;
std::mutex mtx;
void secondThread()
{
while (true)
{
foo.wait(std::unique_lock<std::mutex>(mtx));
std::cout << " ----------------------------" << std::endl;
std::cout << "|processing a notification...|" << std::endl;
std::cout << " ----------------------------" << std::endl;
}
}
int main()
{
std::thread subThread = std::thread(&secondThread);
int count = 0;
while (true)
{
if (count % 10 == 0)
{
foo.notify_one();
}
std::cout << "Main thread working on gathering notifications..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(300));
count++;
}
return 0;
}
根据C ++规范,有人告诉我这个foo.wait(std::unique_lock<std::mutex>(mtx))
代码行不是一个好习惯。这不是解决此类问题的正确方法。它也叫,睡觉(不忙等待)。
答案 0 :(得分:2)
在致电wait
之前,您必须检查您正在等待的事情是否已经发生。在您停止致电wait
之前,您必须检查您正在等待的事情。条件变量是无状态的,不知道你在等什么。编写代码是你的工作。
此外,关联的互斥锁必须保护您正在等待的内容。条件变量的整个要点是提供原子“解锁和等待”操作以防止出现此问题:
但是如果您在等待互联网之前解锁互斥锁之后发生了什么事情呢?你会等待已经发生的事情。
这就是wait
函数获取锁持有者的原因 - 这样它就可以原子地执行步骤3和4。