基于环形队列(信号量 + 锁)的生产者消费者模型

基于环形队列(信号量 + 锁)的生产者消费者模型

ringQueue.hpp(线程安全的环形队列)

c++ 复制代码
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <vector>
#include "sem.hpp"
#include "Mutex.hpp"
using namespace std;

#define RINGQUEUESIZE 10
template <class T>
class RingQueue
{
public:
    RingQueue(int num = RINGQUEUESIZE)
    :num_(num),c_step(0),p_step(0),space_sem_(num),data_sem_(0)
    {
        ring_queue_.reserve(num);
    }
    void push(const T& in)
    {
        space_sem_.P();
        lock_Guard mtx(mtx_);
        ring_queue_[p_step++] = in;
        p_step %= num_;
        //cout<<"push"<<endl;
        data_sem_.V();
    }
    T pop()
    {
        data_sem_.P();
        lock_Guard mtx(mtx_);
        T t = ring_queue_[c_step++];
        c_step %= num_;
        //cout<<"pop"<<endl;
        space_sem_.V();
        return t;
    }
private:
    vector<T> ring_queue_;
    int num_;
    int c_step;
    int p_step;
    Sem space_sem_;
    Sem data_sem_;
    Mutex mtx_;
};

sem.hpp (封装信号量)

c++ 复制代码
#include <iostream>
#include <semaphore.h>
using namespace std;
class Sem
{
public:
    Sem(int value)
    {
        sem_init(&sem_,0,value);
    }
    void P()
    {
        sem_wait(&sem_);
    }
    void V()
    {
        sem_post(&sem_);
    }
    ~Sem()
    {
        sem_destroy(&sem_);
    }
private:
    sem_t sem_;
};

Mutex.hpp (封装锁)

c++ 复制代码
#include <iostream>
#include <cstdlib>
class Mutex
{
public:
    //Mutex(pthread_mutex_t* mutex)
    //:mutex_(mutex)
    Mutex()
    {
        pthread_mutex_init(&mutex_, nullptr);
    }
    void lock()
    {
        pthread_mutex_lock(&mutex_);
    }
    void unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }
    pthread_mutex_t* getMutex()
    {
        return &mutex_;
    }
    ~Mutex()
    {
        pthread_mutex_destroy(&mutex_);
    }

private:
    pthread_mutex_t mutex_;
};

class lock_Guard
{
public:
    lock_Guard(Mutex& mutex)
    :mutex_(mutex)
    {
        mutex_.lock();
    }
    ~lock_Guard()
    {
        mutex_.unlock();
    }
private:
    Mutex& mutex_;
};

Cond.hpp (封装条件变量)

c++ 复制代码
#include <iostream>
#include <cstdlib>
#include "Mutex.hpp"
class Condition_variable
{
public:
    Condition_variable(Mutex& mtx)
    :mtx_(mtx)
    {
        pthread_cond_init(&cond_,nullptr);
    }
    void Wait()
    {
        pthread_cond_wait(&cond_,mtx_.getMutex());
    }
    void notify_one()
    {
        pthread_cond_signal(&cond_);
    }
    void notify_all()
    {
        pthread_cond_broadcast(&cond_);
    }
    ~Condition_variable()
    {
        pthread_cond_destroy(&cond_);
    }
private:
    pthread_cond_t cond_;
    Mutex& mtx_;
};

main.cc

c++ 复制代码
#include "ringQueue.hpp"
#include <pthread.h>
#define CUSTOMERSIZE 2
#define PRODUCTORSIZE 1
class Task
{
public:
    Task(int x,int y)
    :x_(x),y_(y)
    {}
    int operator()()
    {
        return x_ + y_;
    }
    int x_;
    int y_;
};
struct MyThread
{
    RingQueue<Task>* rg;
    string name;
};
void* customer(void* args)
{
    MyThread* mt = (MyThread*)args;
    RingQueue<Task>* rg = mt->rg;
    string name = mt->name;
    //RingQueue<Task>* rg = (RingQueue<Task>*)args;
    sleep(3);
    while(true)
    {
        Task task = rg->pop();
        int ans = task();
        cout << name << ": " << task.x_ << " + " << task.y_ << " = " << ans << endl;
        sleep(1);
    }
    return nullptr;
}
void* productor(void* args)
{
    MyThread* mt = (MyThread*)args;
    RingQueue<Task>* rg = mt->rg;
    string name = mt->name;
    //RingQueue<Task>* rg = (RingQueue<Task>*)args;
    while(true)
    {
        int x = rand()%100+1;
        usleep(100);
        int y = rand()%100+1;
        rg->push(Task(x,y));
        cout << name << ": " << x << " + " << y << " = ?"<<endl;
    }
    return nullptr;
}
int main()
{
    srand(time(NULL));
    RingQueue<Task> rg(5);
    MyThread c_mt[CUSTOMERSIZE];
    MyThread p_mt[PRODUCTORSIZE];
    pthread_t c[CUSTOMERSIZE];
    pthread_t p[PRODUCTORSIZE];
    for(int i=0;i<CUSTOMERSIZE;++i)
    {
        c_mt[i].rg = &rg;
        string name = "customer ";
        name += to_string(i+1);
        c_mt[i].name=name;
        pthread_create(c+i,nullptr,customer,(void*)(c_mt+i));
    } 
    for(int i=0;i<PRODUCTORSIZE;++i)
    {
        p_mt[i].rg = &rg;
        string name = "productor ";
        name += to_string(i+1);
        p_mt[i].name=name;
        pthread_create(p+i,nullptr,productor,(void*)(p_mt+i));
    } 

    for(int i=0;i<CUSTOMERSIZE;++i)
    {
        pthread_join(c[i],nullptr);
    } 
    for(int i=0;i<PRODUCTORSIZE;++i)
    {
        pthread_join(p[i],nullptr);
    } 
    return 0;
}

makefile

makefile 复制代码
ringQueue:main.cc
	g++ -o $@ $^ -std=c++11 -l pthread
.PHONY:clean
clean:
	rm -f ringQueue
相关推荐
SEO_juper8 分钟前
SEO新手入门:什么是SEO及其作用
运维·服务器·搜索引擎·seo·数字营销·seo优化
励志不掉头发的内向程序员32 分钟前
STL库——AVL树
开发语言·c++·学习
ZYMFZ1 小时前
Linux 防火墙 Firewalld
linux·运维·服务器
奔跑吧 android7 小时前
【linux kernel 常用数据结构和设计模式】【数据结构 2】【通过一个案例属性list、hlist、rbtree、xarray数据结构使用】
linux·数据结构·list·kernel·rbtree·hlist·xarray
汉克老师7 小时前
第十四届蓝桥杯青少组C++选拔赛[2023.2.12]第二部分编程题(5、机甲战士)
c++·算法·蓝桥杯·01背包·蓝桥杯c++·c++蓝桥杯
Mr_Xuhhh8 小时前
项目需求分析(2)
c++·算法·leetcode·log4j
NiKo_W8 小时前
Linux 文件系统与基础指令
linux·开发语言·指令
PAK向日葵8 小时前
【C/C++】面试官:手写一个memmove,要求性能尽可能高
c语言·c++·面试
Jared_devin9 小时前
二叉树算法题—— [蓝桥杯 2019 省 AB] 完全二叉树的权值
数据结构·c++·算法·职场和发展·蓝桥杯
搞全栈小苏9 小时前
基于Qt QML和C++的MQTT测试客户端(CMakeLists实现)
xml·c++·qt