实现高效率的消息队列-巧用环形队列

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

volatile u32 head = tail = 0;
os_semophore sem;
bool init()
{
sem.max_val = 1;
sem.init_val = 0;
return true;
}

void put()
{
bool need_wait = need_wake_putter = false;

while (1) {

try_put:
need_wait = need_wake_putter = false;
if (tail == ((head + 1) % len) //full,不必担心出现不一致的情况,请仔细分析
need_wait = true;
else if (tail == head) //empty,不必担心出现不一致的情况,请仔细分析
need_wake_getter = true;

if (need_wait) {
wait_semophore(sem);
goto try_put;
} else {
put_element;
head = (head + 1) % len; //此处不需要对head进行保护,因为只有put线程会修改head
if (need_wake_getter)
increase_semophore(sem);
}
}
}

void get()
{
bool need_wait = need_wake_putter = false;

while (1) {

try_get:
need_wait = need_wake_putter = false;
if (head == tail) //empty,不必担心出现不一致的情况,请仔细分析
need_wait = true;
else if (tail == ((head + 1) % len) //full,不必担心出现不一致的情况,请仔细分析
need_wake_putter =true;

if (need_wait) {
wait_semophore(sem);
goto try_get;
} else {
get_element;
tail = (tail + 1) % len; //此处不需要对tail进行保护,因为只有get线程会修改tail
if (need_wake_putter)
increase_semophore(sem);
}
}
}

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,提高了运行效率。
...全文
991 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuxing_hui 2009-07-16
  • 打赏
  • 举报
回复
有没有大侠发表一下意见?
yuxing_hui 2009-07-05
  • 打赏
  • 举报
回复
有大侠发表一下意见么
很土 2009-07-05
  • 打赏
  • 举报
回复
请参考下我的博客:http://blog.csdn.net/kyee
daidodo 2009-06-29
  • 打赏
  • 举报
回复
sf。
《无锁(lock-free)数据结构》
http://blog.csdn.net/daidodo/archive/2009/02/17/3901293.aspx

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧