基于环形队列的消息队列的实现 (转贴CSDN)

环形队列有一个head指针,有一个tail指针,假设我们用一个环形队列来表示一组资源,
有一个线程产生资源并往队列里发送,另外一个线程从队列里取资源,一般的情况下实现
这样一个功能需要用到OS的互斥/事件/信号量API,在两个线程运行都很快时这些OS的API会带来
比较大的系统开销,怎么样尽可能的减少OS的API调用呢,下面是一个简单的实现方法(假设只有两个
线程,一个往队列里写数据,一个从队列里读数据)

 

 

 

head 与 tail 指针的修改不需要保护,应为分别只有一个线程会修改他们,
put线程会读取tail,修改head, get线程会读取head, 修改tail。
代码中最关键的是goto语句,防止出现误等的情况,比如刚开始时,队列为空,
put线程先运行,该线程会调用increase_semophore语句,然后get线程开始运行,
get线程第一次会取走一个element, 然后get线程继续运行,当它试图取第二个element时,
发现队列为空,于是等待,这时wait_semophore是会成功的,因为put线程之前调用了
increase_semophore,虽然这时get线程会错误的等到资源信号量,但它会跳到try_get标签
处重新检查队列是否为空,这样就避免了出现错误的结果。同时经过仔细分析,两个线程不会死锁。


可能大家会担心一个问题,head和tail指针没有被互斥保护起来,虽不会出现程序的错误运行,比如head和tail
指针的调整出现问题。因为head和tail都只被一个线程修改,所以不存在多个线程修改一个共享变量的情况,所以
这里可以对head和tail不加保护,但我们要保证程序不出逻辑错误,
比如如果getter正在从一个满队列中取一个资源时,修改tail指针时,而在之前运行的putter
线程已经被阻塞在wait_semophore(sem);语句上,那么当getter把资源取走后能不能正确的唤醒
putter线程呢,答案是肯定可以的,因为getter在从一个满队列中取资源时,need_wake_putter
肯定是会被置为true的,所以increase_semophore(sem)肯定会在取资源后被调用,putter线程也
会被正确的唤醒。


这个队列实现机制的优点是最大的避免了调用OS的互斥/事件/信号量API,仅在必须的时候调用
wait_semophore/increase_semophore API,提高了运行效率。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值