为什么 condition_variable 无限期等待
why the condition_variable waits indefinitely
考虑以下代码片段
#include <future>
std::mutex asyncMut_;
std::atomic<bool> isAsyncOperAllowed = false;
std::condition_variable cv;
void asyncFunc()
{
while (isAsyncOperAllowed)
{
std::unique_lock<std::mutex> ul(asyncMut_);
cv.wait(ul, []()
{
return isAsyncOperAllowed == false;
});
}
}
int main()
{
isAsyncOperAllowed = true;
auto fut = std::async(std::launch::async, asyncFunc);
std::this_thread::sleep_for(std::chrono::seconds(3));
std::lock_guard<std::mutex> lg(asyncMut_);
isAsyncOperAllowed = false;
cv.notify_one();
fut.get();
}
我期待一旦我改变 isAsyncOperAllowed 变量的状态并通知条件变量,asyncFunc 中的条件变量应该退出等待,asyncFync 应该 return 并且 main 应该结束。
我观察到条件变量一直在无限期地等待。我做错了什么?
P.S。我在 Win10 - VS2015
死锁:main()
永远不会解锁 lg
所以即使 asyncFunc()
中的 cv
收到通知它也永远不会有机会 运行 因为它可以'申请锁。
尝试:
int main()
{
isAsyncOperAllowed = true;
auto fut = std::async(std::launch::async, asyncFunc);
std::this_thread::sleep_for(std::chrono::seconds(3));
{
std::lock_guard<std::mutex> lg(asyncMut_);
isAsyncOperAllowed = false;
}
cv.notify_one();
fut.get();
}
考虑以下代码片段
#include <future>
std::mutex asyncMut_;
std::atomic<bool> isAsyncOperAllowed = false;
std::condition_variable cv;
void asyncFunc()
{
while (isAsyncOperAllowed)
{
std::unique_lock<std::mutex> ul(asyncMut_);
cv.wait(ul, []()
{
return isAsyncOperAllowed == false;
});
}
}
int main()
{
isAsyncOperAllowed = true;
auto fut = std::async(std::launch::async, asyncFunc);
std::this_thread::sleep_for(std::chrono::seconds(3));
std::lock_guard<std::mutex> lg(asyncMut_);
isAsyncOperAllowed = false;
cv.notify_one();
fut.get();
}
我期待一旦我改变 isAsyncOperAllowed 变量的状态并通知条件变量,asyncFunc 中的条件变量应该退出等待,asyncFync 应该 return 并且 main 应该结束。
我观察到条件变量一直在无限期地等待。我做错了什么?
P.S。我在 Win10 - VS2015
死锁:main()
永远不会解锁 lg
所以即使 asyncFunc()
中的 cv
收到通知它也永远不会有机会 运行 因为它可以'申请锁。
尝试:
int main()
{
isAsyncOperAllowed = true;
auto fut = std::async(std::launch::async, asyncFunc);
std::this_thread::sleep_for(std::chrono::seconds(3));
{
std::lock_guard<std::mutex> lg(asyncMut_);
isAsyncOperAllowed = false;
}
cv.notify_one();
fut.get();
}