等待并在C ++中通知多线程

时间:2018-12-01 05:54:13

标签: c++ multithreading wait notify

我有一个关于等待并在c ++中通知多线程的问题。

我有一个deque<stack<string>> lines的容器,如下所示。

deque(出纳员等候线)

前部(双端)

  

购物车1    -item1-item2-item3


索引2(双端队列)

  

购物车2-项目1         -item2


索引3(双端队列)

  

购物车3 -item1       -item2-item3

我有5条收银台(线程) 我想为每个车道分配推车并进行流程计算。 我问了我的老师,他说我应该使用“等待并通知”。 我仍然不很清楚线程,也不知道如何实现共享资源线程。

3 个答案:

答案 0 :(得分:1)

validateDateForm很可能意味着:

对于每个线程(车道):

  • 有大量等待检查的购物车。

  • 如果队列为空,则线程(收银员)只需validateRange即可将一些购物车排队(只需睡觉,以免浪费CPU)。

  • 如果协调员将新的购物车分配/分配给空队列,那么它应该wait and notify关联的线程(出纳员)醒来以处理从购物车中结账。

    < / li>

然后,您在这里需要实现一个满足以下条件的队列结构:

  • 线程安全(通过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;
}