为什么这段代码中的condition_variable会阻塞?
Why condition_variable in this code blocks?
我是条件变量的新手,我想知道为什么计数器变量后的这段代码块等于99?删除for循环并将"counter += 99"改为使代码工作,它与sleep_for有任何关系吗?谢谢你的帮助:)
#include<thread>
#include<condition_variable>
#include<mutex>
#include<chrono>
#include <iostream>
std::condition_variable cv;
std::mutex mtx;
int counter = 0;
void foo() {
std:: unique_lock<std::mutex>lck{ mtx };
//counter += 99;
for (; counter < 100; counter++) {
std::cout << counter << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
lck.unlock();
cv.notify_one();
}
int main() {
std::thread th(&foo);
{
std::unique_lock<std::mutex>lck{ mtx };
cv.wait(lck, [] {
return counter == 99;
});
}
std::cout << "!!!!!" << std::endl;
th.join();
}
让我们在代码中添加一些注释:
void foo() {
std:: unique_lock<std::mutex>lck{ mtx };
// counter == 0
for (; counter < 100; counter++) {
...
}
// counter == 100
lck.unlock();
cv.notify_one(); // <== notify here
}
我们循环到counter == 100
,此时我们通知cv
。然而,我们正在等待counter == 99
,当它得到通知时,这不是真的。wait()
在代码中返回的唯一方法是在循环的最后一次迭代时发生虚假唤醒。
也许你想循环,而counter < 99
。
#include<thread>
#include<condition_variable>
#include<mutex>
#include<chrono>
#include <iostream>
std::condition_variable cv;
std::mutex mtx;
int counter = 0;
void foo() {
std:: unique_lock<std::mutex>lck{ mtx };
//counter += 99;
for (; counter < 100; counter++) { // B
std::cout << counter << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
lck.unlock();
cv.notify_one(); // C
}
在循环结束时(B), counter的值为100。
int main() {
std::thread th(&foo);
{
std::unique_lock<std::mutex>lck{ mtx };
cv.wait(lck, [] {
return counter == 99; // A
});
}
std::cout << "!!!!!" << std::endl;
th.join();
}
唤醒运行main()
的线程的条件是counter
的值为99 ( a )。
因为在循环结束后调用unlock()
(C),所以counter
的值为100。当counter
的值为99 (A)时,std::condition_variable
才会唤醒它的等待线程。因此,除非在counter
的值为99时,等待线程中有一个虚假的唤醒(这会导致std::condition_variable
的条件计算为true
),否则您的等待线程将永远等待。
您可以通过简单地更改std::condition_variable
的谓词来修复此问题,如下所示:
{
std::unique_lock<std::mutex>lck{ mtx };
cv.wait(lck, [] {
return counter == 100; // CHANGED TO 100 FROM 99.
});
}
或者(排他类型)通过改变for()
循环中的条件,如下所示:
for (; counter < 99; counter++) { // `counter < 100` is now `counter < 99`
std::cout << counter << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
相关文章:
- C++ Singleton - Prevent ::instance() to variable
- 如何通过多类"Union variable" (sfml) 使用轮询事件
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 为什么我会收到"Run-Time Check Failure #2 - Stack around the variable 'pr' was corrupted"错误?
- C++:寻找"returning address of local variable..."的更正
- C++ - 在我尝试制作一个简单的计算器时有一个"uninitialized local variable y used"警告
- Visual Studio Code "variable " u8 的 C/C++ 扩展名 " " 不是类型名称"
- 我需要std::condition,但有两个以上的选择
- C++ "Using Uninitialized Memory.. (variable name) "
- cudaMallocManaged for host-initiated variable
- Cppcheck "Reference to auto variable returned"失败的原因?
- OpenCV 和 C++:"Can't resolve variable 'Mat`"
- 是否有用于"go to variable type definition" C++中"auto"变量的 Visual Studio 键盘快捷方式?
- 冲刺错误"variable may be unsafe" (C4996)...选择?
- Visual Studio生成"Error: uninitialized local variable 'x' "而在线编译器不会 - 为什么?
- GUID variable for JPEG,BMP,PNG
- 如何修复初始化后'stack around variable was corrupted.'变量未更改为分配的值
- C++:从 "const variable*" 转换为"uint32"会失去精度
- C++17 'inline variable' vs 'extern' 关键字继承自 C 的新功能
- Tensorflow C++ API assign variable value