[英]Condition Variable with a while loop in thread in C++
I'm trying to figure out how to use std::condition_variable
in C++ implementing a "strange" producer and consumer program in which I had set a limit to the count
variable. 我试图弄清楚如何在C ++中使用std::condition_variable
来实现“奇怪的”生产者和使用者程序,在该程序中我对count
变量设置了限制。
The main thread ("producer") increments the count and must wait for this to return to zero to issue a new increment. 主线程(“生产者”)递增计数,并且必须等待该计数返回零以发出新的递增值。
The other threads enters in a loop where they have to decrease the counter and issue the notification. 其他线程进入一个循环,在其中它们必须减少计数器并发出通知。
I am blocked because it is not clear to me how to conclude the program by orderly exiting the while loop inside the function of all threads. 我之所以受阻,是因为我不清楚如何通过在所有线程的函数内有序退出while循环来结束程序。
Could someone give me some guidance on how to implement it, please? 有人可以给我一些实施指导吗?
#include <iostream>
#include <thread>
#include <condition_variable>
#include <vector>
int main() {
int n_core = std::thread::hardware_concurrency();
std::vector<std::thread> workers;
int max = 100;
int count = 0;
std::condition_variable cv;
std::mutex mutex;
int timecalled = 0;
for (int i = 0; i < n_core; i++) {
workers.emplace_back(std::thread{[&max, &count, &mutex, &cv]() {
while (true) {
std::unique_lock<std::mutex> lk{mutex};
std::cout << std::this_thread::get_id() << " cv" << std::endl;
cv.wait(lk, [&count]() { return count == 1; });
std::cout << std::this_thread::get_id() << " - " << count << std::endl;
count--;
std::cout << std::this_thread::get_id() << " notify dec" << std::endl;
cv.notify_all();
}
}});
}
while (max > 0) {
std::unique_lock<std::mutex> lk{mutex};
std::cout << std::this_thread::get_id() << " cv" << std::endl;
cv.wait(lk, [&count]() { return count == 0; });
std::cout << std::this_thread::get_id() << " created token" << std::endl;
count++;
max--;
timecalled++;
std::cout << std::this_thread::get_id() << " notify inc" << std::endl;
cv.notify_all();
}
for (auto &w : workers) {
w.join();
}
std::cout << timecalled << std::endl; // must be equal to max
std::cout << count << std::endl; // must be zero
}
The program doesn't end because it is stuck on some final join
. 该程序没有结束,因为它停留在某些最终join
。
The expected result must be: 预期结果必须是:
100
0
EDIT 1 : I replaced max > 0
in the while with a true
. 编辑1:我更换了max > 0
的同时用true
。 Now the loops are unbounded, but using the solution of @prog-fh seems to work. 现在循环是无限的,但是使用@ prog-fh的解决方案似乎可行。
EDIT 2 : I added a variable to check the result in the end. 编辑2 :我添加了一个变量来最后检查结果。
EDIT 3 : I changed while(true)
to while(max >0)
. 编辑3 :我将while(true)
更改为while(max >0)
。 Could this be a problem in concurrency because we are reading it without a lock? 难道这是并发性的问题,因为我们没有锁阅读它?
The threads are waiting for something new in the call cv.wait()
. 该线程正在等待呼叫新的东西 cv.wait()
But the only change that can be observed with the provided lambda-closure is the value of count
. 但是提供的lambda闭包唯一可以观察到的变化是count
的值。
The value of max
must be checked too in order to have a chance to leave this cv.wait()
call. 还必须检查max
的值,以便有机会离开此cv.wait()
调用。
A minimal change in your code could be 您的代码中的最小变化可能是
cv.wait(lk, [&max, &count]() { return count == 1 || max<=0; });
if(max<=0) break;
assuming that changes to max
always occur under the control of the mutex. 假设max
更改始终在互斥锁的控制下发生。
An edit to clarify around the accesses to max
. 修改以澄清对max
的访问。
If the loop run by the threads is now while(true)
, then the max
variable is only read in its body which is synchronised by mutex
(thanks to lk
). 如果线程运行的循环现在为while(true)
,则max
变量仅在其主体中读取,该主体由mutex
体同步(感谢lk
)。
The loop run by the main program is while (max > 0)
: max
is read without synchronisation here but the only thread that can change this variable is the main program itself, so it's pure serial code from this perspective. 主程序运行的循环是while (max > 0)
:这里读取max
没有同步,但是唯一可以更改此变量的线程是主程序本身,因此从这个角度来看,它是纯串行代码。
The whole body of this loop is synchronised by mutex
(thanks to lk
) so it is safe to change the value of max
here since the read operations in the threads are synchronised in the same way. 此循环的整个过程由mutex
(由于lk
)同步,因此可以安全地在此处更改max
的值,因为线程中的读取操作以相同的方式同步。
You're having race conditions: in your code max
may be read by multiple threads, whilst it is being modified in main
, which is a race condition according to C++ standard. 您遇到了竞争状况:在代码中max
可能被多个线程读取,而在main
对其进行了修改,这是根据C ++标准的竞争状况。
The predicates you are using in wait
seems to be incorrect (you're using ==
). 您在wait
中使用的谓词似乎不正确(您正在使用==
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.