我是条件变量的新手,我想知道为什么这段代码在计数器变量后等于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();
}
答案 0 :(得分:1)
让我们为您的代码添加一些注释:
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
时循环。
答案 1 :(得分:0)
(?!.*music$)
在循环结束时( B ),计数器的值为100.
#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
}
唤醒正在运行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()
的值为99( A )。
因为您在完成循环后调用counter
( C ),unlock()
的值为100.您的counter
只会唤醒它std::condition_variable
的值为99( A )时等待线程。因此,除非counter
的值为99(这将导致counter
的条件评估为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()