Linux--线程安全--同步的实现--生产者与消费者模型

31 篇文章 0 订阅

生产者与消费者模型

  • 一种典型的设计模式
  • 设计模式:大佬们针对典型场景设计的解决方案
  • 应用场景:应用于有大量的数据产生以及进行处理的场景
  • 优势:解耦合,支持忙闲不均,支持并发

为了能够支持并发,因此缓冲区必须实现线程安全

  • 生产者与生产者之间应该保持互斥关系
  • 消费者与消费者之间应该保持互斥关系
  • 生产者与消费者之间应该保持同步与互斥关系

实现

  • 两种对应角色的线程(一种入队,一种出队)+ 线程安全的队列
  1. 实现线程安全的队列-- 向外提供入队与出队数据;
  2. 创建线程入队数据,出队数据;

线程安全队列的实现

  • 封装一个线程安全的队列类
  • class BlockQueue --阻塞队列:
  • 有空闲节点可以入队数据,没有空闲节点则阻塞入队线程
  • 有数据节点可以出队数据,没有数据节点则阻塞出队线程
class BlockQueue{
public:
	//构造函数
	BlockQueue(int cap = 5);
	//析构函数
	~BlockQueue();
	bool Push(int data);
	bool Pop(int *data)//通过参数返回地址
private:
	int _capacity;
	std::queue<int> _queue; //非线程安全的
	pthread_mutex_t _mutex;  //实现互斥
	pthread_cond_t _cond_pro; //生产者等待队列
	pthread_cond_t _cond_cus; //消费者等待队列
};
#include<iostream>
#include<queue>
#include<pthread.h>
#include<cstdio>
class BlockQueue
{ 
public:
  //构造函数
  BlockQueue(int cap = 5):_capacity(cap)
  {
    //初始化
    pthread_mutex_init(&_mutex, NULL);
    pthread_cond_init(&_cond_pro, NULL);
    pthread_cond_init(&_cond_cus, NULL);
  }
  //析构函数
  ~BlockQueue()
  {
    //销毁
    pthread_mutex_destroy(&_mutex);
    pthread_cond_destroy(&_cond_pro);
    pthread_cond_destroy(&_cond_cus);
  }
  //入队
  bool Push(int data)
  {
    pthread_mutex_lock(&_mutex);//加锁
    while(_queue.size() == _capacity)
    {
      pthread_cond_wait(&_cond_pro, &_mutex);//阻塞,等待在生产者队列
    }
    _queue.push(data);//入队
    pthread_cond_signal(&_cond_cus);//唤醒消费者(至少一个)
    pthread_mutex_unlock(&_mutex);//解锁
    return true;
  }
  //出队
  bool Pop(int *data)
  {
    pthread_mutex_lock(&_mutex);//加锁
    //前提要有数据,判空 
    while(_queue.empty())
    {
      pthread_cond_wait(&_cond_cus, &_mutex);//阻塞,等待在消费者队列
    }
    *data = _queue.front();//获取队首元素
    _queue.pop();//出队
    pthread_cond_signal(&_cond_pro);//唤醒生产者
    pthread_mutex_unlock(&_mutex);//解锁
    return true;
  }
private:
  int _capacity;
  std::queue<int> _queue;
  pthread_mutex_t _mutex;
  pthread_cond_t _cond_pro;
  pthread_cond_t _cond_cus;
};
void *productor(void *arg)
{
  BlockQueue *q = (BlockQueue*)arg;//强转获取到数据
  int i = 0;
  while(1)
  {
    q->Push(i);//入队
    printf("生产者:%d\n",i++);
  }
  return NULL;
}
void *customer(void *arg)
{
  BlockQueue *q = (BlockQueue*)arg;
  while(1)
  {
    int data;
    q->Pop(&data);
    printf("消费者:%d\n", data);
  }
  return NULL;
}
int main(int argc, char* argv[])
{
  BlockQueue q;//实例化一个对象
  pthread_t ptid[4], ctid[4];
  int ret;
  for(int i = 0; i < 4; i++)
  {
    //创建线程
    ret = pthread_create(&ptid[i], NULL, productor, &q);
    if(ret != 0)
    {
      printf("create thread error!\n");
      return -1;
    }
  }
  for(int i = 0; i < 4; i++)
  {
    ret = pthread_create(&ctid[i], NULL, customer, &q);
    if(ret != 0)
    {
      printf("create thread error!\n");
      return -1;
    }
  }
  for(int i = 0; i < 4; i++)
  {
    pthread_join(ptid[i], NULL);
    pthread_join(ctid[i], NULL);
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值