Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40768
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 285
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-08 13:03
个人简介

海纳百川有容乃大,壁立千仞无欲则刚。

文章分类
文章存档

2015年(17)

2014年(12)

我的朋友

分类: LINUX

2015-02-16 10:03:59


  1. #include <pthread.h>

  2. struct msg {
  3.         struct msg *m_next;
  4.         /* ... more stuff here ... */
  5. };

  6. struct msg *workq;
  7. pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
  8. pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

  9. void
  10. process_msg(void)
  11. {
  12.         struct msg *mp;

  13.         for (;;) {
  14.                 pthread_mutex_lock(&qlock);
  15.                 while (workq == NULL)
  16.                         pthread_cond_wait(&qready, &qlock);
  17.                 mp = workq;
  18.                 workq = mp->m_next;
  19.                 pthread_mutex_unlock(&qlock);
  20.                 /* now process the message mp */
  21.         }
  22. }

  23. void
  24. enqueue_msg(struct msg *mp)
  25. {
  26.         pthread_mutex_lock(&qlock);
  27.         mp->m_next = workq;
  28.         workq = mp;
  29.         pthread_mutex_unlock(&qlock);
  30.         pthread_cond_signal(&qready);
  31. }
书上的示例代码如下,我的问题是,为什么不能将19行的while 改为 if (之前在我自己的代码里我用的就是if)
书上示例的下面有一段解说的文字。但是,对于我的疑问却解释的不是很清楚。最后自己想了很长时间终于想通了。

情况是这样的:
process_msg这个方法,可能被一个进程中的多个线程同时调用,换句话说,就是进程中有多个线程同时用于消息处理。
如果将代码中的while改为if,那么在以下这种情况下就会出错。

系统连续两次调用了 enqueue_msg,此时队列里面添加了两个消息和收到两次 pthread_cond_signal通知。
收到第一个pthread_cond_signal通知时,某个代码停在20行的线程被唤醒。此时可能由于该线程处理的太快,这一个线程连续两次执行消息处理。上下文再次切换。以下分别对 while 和 if 作分析:
    A. 19行是一个while,情况如下:
        收到第二个pthread_cond_signal通知。某个代码停在20行的线程被唤醒继续往下运行。由于此时的代码是 while(workq == NULL) pthread_cond_wait(&qready, &qlock)。唤醒的线程会执行 workq == NULL 判断。发现 workq为空,继续等待。

    B. 19行是一个if,情况如下:
       收到第二个pthread_cond_signal通知。某个代码停在20行的线程被唤醒继续往下运行。由于此时的代码是 if(workq == NULL) pthread_cond_wait(&qready, &qlock) 。唤醒的线程继续往下走,而不会再次判断 workq的情况。而此时 workq 却等于 NULL,BUG就此产生了。

这种BUG非常难查找,它只会在系统长期间运行而且很繁忙的时候出现。一旦出现将会是致命性的。

读书还是要踏踏实实,书里的经验,都是前人血的教训总结出来的。
阅读(300) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~