zoukankan      html  css  js  c++  java
  • C++多线程 生产者 消费者示例

    之前写过一篇关于多线程的https://blog.csdn.net/qq_21049875/article/details/79589126。
      为了复习一下C++多线程的使用,以及程序的编写,于是写了一个生产者与消费者。
      在编写的过程中了解了条件变量(std::condition_variable)的使用,可以让线程挂起和叫醒线程,以及之前编写一些示例代码的时候一直用的是std::locak_guard,而不是std::unique_lock,两者都是RAII(获取资源立即初始化 ),而后者比较灵活,提供了lock(),unlock(),try_lock(),接口。
      std::unique_lock的源代码中大概是封装了mutex的一些接口,下面从其他博客复制了mutex的接口信息。)
      lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
        (1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
        (2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
        (3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
      unlock(), 解锁,释放对互斥量的所有权。
      try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况:
        (1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。
        (2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
        (3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。

      下面代码编写中碰到的问题,在productItem与consumeItem的时候,都有对互斥量mtx上锁的过程,在productItem的代码里有一个Sleep,是为了让消费者能够消费到商品,要不然就由于计算机速度太快,直接生产满了,就碰到while(item…)直接出发is_full造成后面运行后生产者进入死锁状态。
      当然,你可以编写一个对is_full这个条件变量相应的函数,比如item满了就扔掉一个,去解锁is_full然后唤醒product线程,这样就不需要Sleep函数啦~
      还有,可以用std::this_thread::yield()来实现把执行的线程时间片让给其他线程使用,就比如item满了之后让其他线程运行,或者是std::this_thread::sleep_for() 让线程睡一下,更或者直接sleep……hah….

    代码:

    #include<iostream>
    #include<vector>
    #include<thread>
    #include<queue>
    #include<mutex>
    #include<Windows.h>

    class demo {
    private:
    condition_variable is_full;
    condition_variable is_empty;
    mutex mtx;
    vector<std::thread> tpool;
    private:
    queue<int> item_buff;
    const int buffsize;
    static int item_id;
    int c_no, p_no;
    private:
    void producItem() {
    while (true) {
    std::unique_lock<mutex> lck(mtx);
    while (item_buff.size() == buffsize) {
    is_full.wait(lck);
    }
    item_id = item_id++ %buffsize;
    item_buff.push(item_id);
    cout << "product item id: " << item_id << endl;
    lck.unlock();
    is_empty.notify_all();
    Sleep(10);
    }
    }
    void consumeItem() {
    while (true) {
    std::unique_lock<mutex> lck(mtx);
    while (item_buff.empty()) {
    cout << "wait product" << endl;
    is_full.notify_one();
    is_empty.wait(lck);
    }
    cout << "customer id : " << this_thread::get_id() << endl;
    cout << "consume Item id: " << item_buff.front() << endl;
    item_buff.pop();
    lck.unlock();
    }
    }
    public:
    demo(int size = 10, int pno = 1, int cno = 5) :buffsize(size), p_no(pno), c_no(cno) {};
    void run() {
    productTask();
    customerTask();
    for (auto &i : tpool) {
    i.join();
    }
    }
    void productTask() {
    for (int i = 0; i < p_no; i++) {
    tpool.emplace_back(thread(&demo::producItem, this));
    }
    }
    void customerTask() {
    for (int i = 0; i < c_no; i++) {
    tpool.emplace_back(thread(&demo::consumeItem, this));
    }
    }
    };

    int demo::item_id = 0;

    int main()
    {
    demo t;
    t.run();
    return 0;
    }

  • 相关阅读:
    网页字体大小控制
    表格文本框搜索匹配
    表格展开和关闭
    表格复选框控制行高亮
    jquery表单验证
    文本框变大变小效果--jQuery
    滚动条高度变化jQuery
    点击标题显示隐藏效果--jQuery
    jQuery练习2-1
    jQuery练习2
  • 原文地址:https://www.cnblogs.com/tsh292278/p/10508573.html
Copyright © 2011-2022 走看看