IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    关于pthread_cond_wait使用while循环判断的理解

    admin发表于 2012-06-28 13:23:37
    love 0

    在Stevens的《Unix 环境高级编程》中第11章线程关于pthread_cond_wait的介绍中有一个生产者-消费者的例子P311,
    在进入pthread_cond_wait前使用while进行条件判断,而没有直接使用if,耐人费解!

    代码如下:

    #include 
    struct msg {
      struct msg *m_next;
      /* value...*/
    };
    
    struct msg* workq;
    pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
    
    void
    process_msg() {
      struct msg* mp;
      for (;;) {
        pthread_mutex_lock(&qlock;);
    	while (workq == NULL) {
    	  pthread_cond_wait(&qread;, &qlock;);
    	}
    	mq = workq;
    	workq = mp->m_next;
    	pthread_mutex_unlock(&qlock;);
    	/* now process the message mp */
      }
    }
    
    void
    enqueue_msg(struct msg* mp) {
    	pthread_mutex_lock(&qlock;);
    	mp->m_next = workq;
    	workq = mp;
    	pthread_mutex_unlock(&qlock;);
    	/** 此时另外一个线程在signal之前,执行了process_msg,刚好把mp元素拿走*/
    	pthread_cond_signal(&qready;);
    	/** 此时执行signal, 在pthread_cond_wait等待的线程被唤醒,
    	    但是mp元素已经被另外一个线程拿走,所以,workq还是NULL ,因此需要继续等待*/
    }
    

    这里process_msg相当于消费者,enqueue_msg相当于生产者,struct msg* workq作为缓冲队列

    解释如下

    在process_msg中使用while(workq==NULL)循环判断条件,这里主要是因为在enqueue_msg中unlock之后才唤醒等待
    的线程,会出现上述注释出现的情况,造成workq==NULL,因此需要继续等待。

    但是如果将pthread_cond_signal移到pthread_mutex_unlock()之前执行,则会避免这种竞争,在unlock
    之后,会首先唤醒pthread_cond_wait的线程,进而workq!=NULL总是成立。

    因此建议使用while循环进行验证,以便能够容忍这种竞争。

    您可能对下面文章也感兴趣:

    • Pthreads并行编程之spin lock与mutex性能对比分析[zz]
    • 使用Bash中Complete自动补全命令
    • Unix/Linux设计思想学习笔记之一
    • Linux中关于Cache Memory的介绍
    • [shell学习笔记]sort、uniq、cut、paste和split用法详解


沪ICP备19023445号-2号
友情链接