单生产者-单消费者模型 产品库位于线程函数外

参考资料

c++ 11 多线线程系列-----------生产者消费者
C11线程管理:互斥锁

需求

需要构成一个生产者消费者模式,生产者和消费者是无继承关系的两个类的各自的对象,作用与两个不同的线程中。产品库设计在两个线程之外。

方法

将产品库容器的地址作为参数传入线程函数,在线程中将该地址传入类的构造函数,在对象中对该地址进行互斥的读写。

关键原料

#include <mutex>
std::mutex g_lock;

提供一个锁,其实也考虑过CRITICAL_SECTION,其开销较mutex更低,但是下面的方法

#include <condition_variable>
std::condition_variable not_empty;

需要配合mutex使用,具体方法为

std::unique_lock<std::mutex> lck(g_lock);
not_empty.wait(lck);			// 挂起当前线程
...
not_empty.notify_all();			// 释放

由于g_locknot_empty是全局变量,可以在另一线程中为被挂起的当前线程进行释放
还有一点,unique_lock<mutex>的使用可以省去lock()unlock()语句的繁琐,提升了安全性又不失自由度。(默认在作用域生命周期结束时解锁)。

实例

代码

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <queue>

std::mutex g_lock;							// 互斥
std::condition_variable not_empty;			// 挂起条件

class CSHIT {
    
    
    int shittime;
    std::queue<char>* shitpool;
public:
    CSHIT(std::queue<char> * sp) {
    
    
        shittime = 3;
        shitpool = sp;
    }
    void makeshit() {
    
    
        std::unique_lock<std::mutex> lck(g_lock);
        std::cout << "Making shit:" << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(shittime));
        (*shitpool).push('S');
        not_empty.notify_all();									// 一旦生产一枚产品,通知消费者线程释放
        std::cout << "Shit made:" << std::this_thread::get_id() << std::endl;
        showshitpoolsize();
    }
private:
    void showshitpoolsize() {
    
    
        std::cout << "Shit Pool Size: " << (*shitpool).size() << std::endl;
    }
};

class CEAT {
    
    
    int eattime;
    std::queue<char>* shitpool;
public:
    CEAT(std::queue<char>* sp) {
    
    
        eattime = 1;
        shitpool = sp;
    }
    void eatshit() {
    
    
        std::unique_lock<std::mutex> kcl(g_lock);
        while ((*shitpool).empty()) {
    
    							// 检查产品区是否有产品
            std::cout << "I'm hungry!!" << std::endl;
            not_empty.wait(kcl);								// 若无产品,挂起当前线程
        }
        std::cout << "Eating shit:" << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(eattime));
        (*shitpool).pop();
        std::cout << "Shit eaten:" << std::this_thread::get_id() << std::endl;
        showshitpoolsize();
    }
private:
    void showshitpoolsize() {
    
    
        std::cout << "Shit Pool Size: " << (*shitpool).size() << std::endl;
    }
};

void vFunc1(std::queue<char>* sp)
{
    
    
    CSHIT shit(sp);
    for (int s = 0; s < 10; ++s) {
    
    
        shit.makeshit();
    }
}

void vFunc2(std::queue<char>* sp) {
    
    
    CEAT eat(sp);
    for (int j = 0; j < 10; ++j) {
    
    
        eat.eatshit();
    }
}

int main()
{
    
    
    std::queue<char> ShitPool;
    for (int i = 0; i < 3; ++i) {
    
    
        ShitPool.push('S');
    }

    std::thread t1(vFunc1, &ShitPool);
    std::thread t2(vFunc2, &ShitPool);

    t1.join();
    t2.join();

    return 0;
}

结果

Eating shit:4776
Shit eaten:4776
Shit Pool Size: 2
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 1
Making shit:16284
Shit made:16284
Shit Pool Size: 2
Making shit:16284
Shit made:16284
Shit Pool Size: 3
Making shit:16284
Shit made:16284
Shit Pool Size: 4
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 3
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 2
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 1
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 0
I'm hungry!!
Making shit:16284
Shit made:16284
Shit Pool Size: 1
Making shit:16284
Shit made:16284
Shit Pool Size: 2
Making shit:16284
Shit made:16284
Shit Pool Size: 3
Making shit:16284
Shit made:16284
Shit Pool Size: 4
Making shit:16284
Shit made:16284
Shit Pool Size: 5
Making shit:16284
Shit made:16284
Shit Pool Size: 6
Making shit:16284
Shit made:16284
Shit Pool Size: 7
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 6
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 5
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 4
Eating shit:4776
Shit eaten:4776
Shit Pool Size: 3

I'm hungry!!提示消费者线程被挂起。线程之间的运转由CPU的scheduler分配,可视为随机。

猜你喜欢

转载自blog.csdn.net/weixin_54940900/article/details/114108271