缓冲区设计—线程间通讯

书接上回。

上一篇里,我们设计并实现了环形队列的数据结构。同时留下了下面的更具复杂性的问题:

  • 对于push的操作,需要操作前等待队列已经有了空间,也就是说队列没有满的状态。等到这个状态出现了,才继续进行push的操作,否则,push操作挂起。
  • 对于get 的操作,需要操作前等待队列有了数据,也就是说队列不为空的状态。等到这个状态出现了,才继续进行get的操作,否则,get操作挂起。
  • 上面的push操作/get操作一般是不同的进程和线程。同时,也有可能有多个push的操作和get操作的进程和线程。

以上分析,可以看到,push和get都有一个等待满足条件的等待状态。

  • push等待的条件是队列为有空闲的状态,当get操作后,就会腾出队列空间,从而可能满足push的条件。那么,get操作后,就需要通知push,让push从等待转入测试判断,如果条件满足,则会进行push的操作。
  • 另一方面,get等待的条件是队列为有数据的的状态,当put操作后,就会将数据插入到队列中,从而可能满足get的条件。那么,push操作后,就需要通知get,让get从等待转入测试判断,如果条件满足,则会进行get的操作。

上面的push和get的等待问题都可以归结为资源生产和消费的问题。

 

 

设资源数为nresource。

 

资源生产方进行下面的流程:

  • 资源生产操作;
  • nresource加一;
  • 通知资源消费方。

资源消费方则为下面的流程:

  • 等待来自于生产方的通知;
  • 判断是否资源数 nresource大于零,如果条件不满足,回到上一条;
  • 进行资源消费的操作;
  • nresource减一。

这里,这个资源生产和消费的核心技术是等待和通知技术。使用System V的信号灯以及Posix的信号灯技术可以实现这个功能。在这里,我选择另一个更高效的线程锁和条件变量的技术来实现。

 

具体的实现的程序的架构:

定义变量:
pthread_mutex_t mutex;
pthread_cond_t cond;
int nresouce;
进行变量的初始化,nresource设置为资源的初始数目。例如,对于队列的put操作,其初始值为队列的大小,而对于队列的get操作,初始值应为0。

生产方:
pthread_mutex_lock(&mutex);
produce_resource(); // 产生资源
nresource++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

消费方:
pthread_mutex_lock(&mutex);
while ( nresource < 1 )
pthread_cond_wait(&cond, &mutex);
consume_resource(); // 消费资源
nresource--;
pthread_mutex_unlock(&mutex);


  • pthread_mutex_lock及pthread_mutex_unlock是一对加锁和解锁的过程,用于界定临界区范围。
  • pthread_cond_signal会唤醒在同样的参数cond下调用pthread_cond_wait的休眠的线程。
  • 显然,pthread_cond_wait是使线程进入休眠状态,等待来自于pthread_cond_signal的唤醒。它们靠同样的参数cond联系在一起。

在我们这个实际的环形队列的方案中,push及get实际上是互相的生产者和消费者。push为get生产队列数据,get消费队列数据;而get为push生产队列空间的资源,push消费队列空间资源。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值