我有一个关于等待并在c ++中通知多线程的问题。
我有一个deque<stack<string>> lines
的容器,如下所示。
前部(双端)
购物车1 -item1-item2-item3
索引2(双端队列)
购物车2-项目1 -item2
索引3(双端队列)
购物车3 -item1 -item2-item3
我有5条收银台(线程) 我想为每个车道分配推车并进行流程计算。 我问了我的老师,他说我应该使用“等待并通知”。 我仍然不很清楚线程,也不知道如何实现共享资源线程。
答案 0 :(得分:1)
validateDateForm
很可能意味着:
对于每个线程(车道):
有大量等待检查的购物车。
如果队列为空,则线程(收银员)只需validateRange
即可将一些购物车排队(只需睡觉,以免浪费CPU)。
如果协调员将新的购物车分配/分配给空队列,那么它应该wait and notify
关联的线程(出纳员)醒来以处理从购物车中结账。
然后,您在这里需要实现一个满足以下条件的队列结构:
线程安全(通过wait
)
可通知的(按notify
)
您可以参考this trivial implementation以获得更多详细信息。
答案 1 :(得分:0)
由于您未提供任何代码,我们只能猜测!
好吧,您很可能会拥有一些“购物车”,例如等待分配给收银员的中心线。由于多个车道可以同时变为“自由行”,因此您需要注意踩踏安全性。
线程安全性很简单,只需创建一个中央std :: mutex并将出队例程和空的中央通道检查包装在包含std :: scoped_lock(your_global_mutex)的{}范围内即可。
现在,如果当前中线没有手推车等待,该怎么办?然后,所有收银员线程都必须等待(),直到中心线通知()有关新购物车可用。为此,您必须锁定收银员线程: 您将需要一个条件变量和一个互斥量。等待是这样的,只要这些线程之一检测到购物车行为空(但在范围锁之外),就应该执行等待!
std::unique_lock<std::mutex> lk(your_condition_variable_mutex);
your_condition_variable.wait(lk, []{return i == 1;});
确保您具有全局变量 int i = 0; 之类的东西,因为wait()有时会无缘无故地唤醒-如果没有notify call()。
现在,每次将新购物车添加到主行时,都将i = 1设置为1,并在条件变量上调用notiftAll()! (记住,请在正确的时间将其设置回0-例如,在从中心线取出最后一个购物车之前不久,例如由全局互斥锁的scoped_lock保护)
答案 2 :(得分:-1)
这里有一个可以正常工作的代码,可以解决您的问题-请原谅我goto的风格不好:)解释在我的其他答案中!
(注意:使用pthread-> g ++ test.cc -pthread进行编译)
#include <stdio.h>
#include <condition_variable>
#include <thread>
#include <functional>
#include <iostream>
#include <stack>
volatile int i = 0;
std::mutex global_mutex;
std::mutex cond_mutex;
std::condition_variable cv;
std::stack<int> carts;
void cashier(int line){
int cart;
begin:
{
std::lock_guard<std::mutex> lc(global_mutex);
if(carts.size() == 0){
i = 0;
goto nah;
}
cart = carts.top();
carts.pop();
}
goto yay;
nah:
{
std::unique_lock<std::mutex> lk(cond_mutex);
{
std::lock_guard<std::mutex> lc(global_mutex);
std::cerr << "Cashier " << line << " Waiting... \n";
}
cv.wait(lk, []{return i == 1;});
goto begin;
}
yay:
{
std::lock_guard<std::mutex> lc(global_mutex);
std::cerr << "Cashier " << line << " got cart " << cart << " ... \n";
}
goto begin;
}
int main () {
std::thread t1(std::bind(cashier,1));
std::thread t2(std::bind(cashier,2));
std::thread t3(std::bind(cashier,3));
std::thread t4(std::bind(cashier,4));
std::thread t5(std::bind(cashier,5));
int cntr = 1;
printf("PRESS ENTER TO ENQUEUE NEW CART!!!\n");
while(getchar()){
{
std::lock_guard<std::mutex> lc(global_mutex);
carts.push(cntr);
cntr ++;
i = 1;
cv.notify_all();
}
}
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
return 0;
}