同步:生产者消费者模型(条件变量与信号量)

本小妞迷上赌 提交于 2019-12-18 02:16:00

同步

  1. 什么是同步:
    通过条件判断实现对临界资源访问的合理性
  2. 实现:
    条件变量:当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。所以用条件变量可以睡眠的等待某一种条件出现。
  3. 原理:
    向外提供一个等待队列,以及等待与唤醒的功能

生产者消费者模型

在这里插入图片描述
一、一个交易场所

二、两个角色:生产者和消费者

三、三种关系:

  1. 生产者和生产者:互斥
  2. 生产者和消费者:互斥与同步
  3. 消费者和消费者:互斥

优点:

  1. 解耦
  2. 支持并发
  3. 忙闲不均

pthread_cond_wait 调用等待时释放锁,唤醒时重新获得锁

生产者消费者模型

 10 class BlockQueue
 11 {
 12     private:
 13         queue<int> q;
 14         int cap;
 15         pthread_mutex_t lock;
 16         pthread_cond_t c_cond;
 17         pthread_cond_t p_cond;

 55     public:
 56         BlockQueue(int cap_ = 4)
 57             :cap(cap_)
 58         {
 59             pthread_mutex_init(&lock, nullptr);
 60             pthread_cond_init(&c_cond,nullptr);
 61             pthread_cond_init(&p_cond,nullptr);
 62         }
 63         //producter
 64         void PushData(int data)
 65         {
 66             LockQueue();
 67             if(QueueIsFull())
 68             {
 69                 cout << "queue is full" <<endl;
 70                 SignalConsumer();
 71                 ProducterWait();
 72             }
 73             q.push(data);
 74             UnlockQueue();
 75         }
 76         //Consumer
 77         void PopData(int &out)
 78         {
 79             LockQueue();
 80             if(QueueIsEmpty())
 81             {
 82                 cout << "queue is empty" <<endl;
 83                 SignalProducter();
 84                 ConsumerWait();
 85             }
 86             out = q.front();
 87             q.pop();
 88             UnlockQueue();
 89         }
 90         ~BlockQueue()
 91         {
 92             pthread_mutex_destroy(&lock);
 93             pthread_cond_destroy(&c_cond);
 94             pthread_cond_destroy(&p_cond);
 95         }
 96 };

在这里插入图片描述

信号量

信号量是一个计数器,用来描述临界资源的数目,提供等待队列,提供等待与唤醒的功能接口。

实现同步:通过自身的计数器功能进行资源计数,对临界资源访问之前先访问信号量,通过计数判断是否有资源能够访问,若不能访问,等待计数-1(所以信号量为负几,则表示有多少线程在等待)

环形队列
环状结构起始状态和结束状态一样,不好判断空还是满,所以可以加入计数器在这里插入图片描述

 11 class RingQueue{
 12     private:
 13         vector<int> buf;
 14         int cap;
 15         sem_t sem_blank;
 16         sem_t sem_data;
 17 
 18         int c_step;
 19         int p_step;
 20     private:
 21         void P(sem_t &s)
 22         {
 23             sem_wait(&s);
 24         }
 25         void V(sem_t &s)
 26         {
 27             sem_post(&s);
 28         }
 29     public:
 30         RingQueue(int cap_ = 1024)
 31             :cap(cap_),
 32             buf(cap_)
 33         {
 34             c_step = p_step = 0;
 35             sem_init(&sem_blank, 0, cap);
 36             sem_init(&sem_data, 0, 0);
 37         }
 38         void PopData(int &data)
 39         {
 40             P(sem_data);
 41             data = buf[c_step];
 42             c_step ++;
 43             c_step %= cap;
 44             V(sem_blank);
 45         }
 46         void PushData(const int &data)
 47         {
 48             P(sem_blank);
 49             buf[p_step] = data;
 50             p_step ++;
 51             p_step %= cap;
 52             V(sem_data);
 53         }
 54         ~RingQueue()
 55         {
 56             sem_destroy(&sem_blank);
 57             sem_destroy(&sem_data);
 58         }
 59 };

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!