pthread_cond_wait()加一个while为什么的解释

原创 2011年08月02日 15:39:30

等号上面这段是大多数网上给pthread_cond_wait()加一个while为什么的解释:但是有些地方不太明白或者说没有解释清晰:
准备:1:pthread_cond_singal是唤醒至少一个线程的(而不是sinal的意思,仅仅唤醒一个线程)。
     2:把下面while(x<y)当成thread1;while(x<z)当成thread2;if(x>y) 当成thread3.
解释:首先当thread1和thread2允许while时,发现条件都成立,那么就允许pthread_cond_wait();
     然后当thread3时发送pthread_cond_singal;唤醒了thread2和thread3;唤醒后就会进行while判断。x>y,那么thread1不用pthread_cond_wait,就可以运行下去了。
     而x<z不成立,继续执行pthread_cond_wait.所以就保证了只唤醒一个线程
==============================================================================================================

条件锁(条件Mutex)pthread_cond_wait、pthread_cond_signal
2011/06/18 10:58
  条件锁(条件Mutex)pthread_cond_wait、pthread_cond_signal、pthread_cond_broadcast的使用收藏
LINUX环境下多线程编程肯定会遇到需要条件变量的情况,此时必然要使用pthread_cond_wait()函数。但这个函数的执行过程比较难于理解。
    pthread_cond_wait()的工作流程如下(以MAN中的EXAMPLE为例):
       Consider two shared variables x and y, protected by the mutex mut, and a condition vari-
       able cond that is to be signaled whenever x becomes greater than y.

              int x,y;
              pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
              pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

       Waiting until x is greater than y is performed as follows:

              pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
              /* operate on x and y */
              pthread_mutex_unlock(&mut);

       Modifications on x and y that may cause x to become greater than y should signal the con-
 dition if needed:

              pthread_mutex_lock(&mut);
              /* modify x and y */
              if (x > y) pthread_cond_singal(&cond);
              pthread_mutex_unlock(&mut);

     这个例子的意思是,两个线程要修改X和 Y的值,第一个线程当X<=Y时就挂起,直到X>Y时才继续执行(由第二个线程可能会修改X,Y的值,当X>Y时唤醒第一个线程),即首先初始化一个普通互斥量mut和一个条件变量cond。之后分别在两个线程中分别执行如下函数体:

              pthread_mutex_lock(&mut);
              while (x <= y) {
                      pthread_cond_wait(&cond, &mut);
              }
              /* operate on x and y */
              pthread_mutex_unlock(&mut);
和:       pthread_mutex_lock(&mut);
              /* modify x and y */
              if (x > y) pthread_cond_signal(&cond);
              pthread_mutex_unlock(&mut);
    其实函数的执行过程非常简单,在第一个线程执行到pthread_cond_wait(&cond,&mut)时,此时如果X<=Y,则此函数就将mut互斥量解锁,再将cond条件变量加锁 ,此时第一个线程挂起 (不占用任何CPU周期)。
    而在第二个线程中,本来因为mut被第一个线程锁住而阻塞,此时因为mut已经释放,所以可以获得锁mut,并且进行修改X和Y的值,在修改之后,一个IF语句判定是不是X>Y,如果是,则此时pthread_cond_signal()函数会唤醒第一个线程,并在下一句中释放互斥量mut。然后第一个线程开始从pthread_cond_wait()执行,首先要再次锁mut , 如果锁成功,再进行条件的判断 (至于为什么用WHILE,即在被唤醒之后还要再判断,后面有原因分析),如果满足条件,则被唤醒进行处理,最后释放互斥量mut 。

    至于为什么在被唤醒之后还要再次进行条件判断(即为什么要使用while循环来判断条件),是因为可能有“惊群效应”。有人觉得此处既然是被唤醒的,肯定是满足条件了,其实不然。如果是多个线程都在等待这个条件,而同时只能有一个线程进行处理,此时就必须要再次条件判断,以使只有一个线程进入临界区处理。对此,转来一段:

引用下POSIX的RATIONALE:

Condition Wait Semantics

It is important to note that when pthread_cond_wait() and pthread_cond_timedwait() return without error, the associated predicate may still be false. Similarly, when pthread_cond_timedwait() returns with the timeout error, the associated predicate may be true due to an unavoidable race between the expiration of the timeout and the predicate state change.

The application needs to recheck the predicate on any return because it cannot be sure there is another thread waiting on the thread to handle the signal, and if there is not then the signal is lost. The burden is on the application to check the predicate.

Some implementations, particularly on a multi-processor, may sometimes cause multiple threads to wake up when the condition variable is signaled simultaneously on different processors.

In general, whenever a condition wait returns, the thread has to re-evaluate the predicate associated with the condition wait to determine whether it can safely proceed, should wait again, or should declare a timeout. A return from the wait does not imply that the associated predicate is either true or false.

It is thus recommended that a condition wait be enclosed in the equivalent of a "while loop" that checks the predicate.

从上文可以看出:
1,pthread_cond_signal在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它被唤醒的线程就需要继续 wait,while循环的意义就体现在这里了,而且规范要求pthread_cond_signal至少唤醒一个pthread_cond_wait上的线程,其实有些实现为了简单在单处理器上也会唤醒多个线程.
2,某些应用,如线程池,pthread_cond_broadcast唤醒全部线程,但我们通常只需要一部分线程去做执行任务,所以其它的线程需要继续wait.所以强烈推荐此处使用while循环.

       其实说白了很简单,就是pthread_cond_signal()也可能唤醒多个线程,而如果你同时只允许一个线程访问的话,就必须要使用while来进行条件判断,以保证临界区内只有一个线程在处理。
====================================================================================================================================

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

在Stevens的《Unix 环境高级编程》中第11章线程关于pthread_cond_wait的介绍中有一个生产者-消费者的例子P311, 在进入pthread_cond_wait前使用while...
  • ywy2090
  • ywy2090
  • 2013年10月29日 18:21
  • 814

为什么pthread_cond_wait需要传递mutex参数

这是来自知乎的一个问题,由@吴志强提出,有意思的是,他看了大家的回答后,突然顿悟了,同时也发现有人答错了,于是乎,他自己回答了自己的问题。我看完后,发现他分析的很精彩,于是就记录在这。下面是他的自答:...
  • booirror
  • booirror
  • 2014年06月13日 01:10
  • 2647

互斥量、条件变量与pthread_cond_wait()函数的使用,详解(二)

1.Linux“线程”      进程与线程之间是有区别的,不过Linux内核只提供了轻量进程的支持,未实现线程模型。Linux是一种“多进程单线程”的操作系统。Linux本身只有进程的概念,而...
  • cnclenovo
  • cnclenovo
  • 2015年03月24日 11:30
  • 3959

以公司实际应用讲解OpenStack到底是什么

可能很多人从Ubuntu和HP的新闻当中听说过OpenStack,知道它跟云计算相关,可是OpenStack究竟是做什么的,可能不少人还只有比较模糊的感觉。而在之前一篇《OpenStack实践之旅:安...
  • madun
  • madun
  • 2013年07月31日 15:15
  • 1459

白话解释hadoop是做什么的

hadoop是什么? (1)Hadoop是一个开源的框架,可编写和运行分布式应用处理大规模数据,是专为离线和大规模数据分析而设计的,并不适合那种对几个记录随机读写的在线事务处理模式。Hadoop=H...
  • fzq1988215
  • fzq1988215
  • 2015年03月04日 10:40
  • 308

基于条件变量阻塞pthread_cond_wait

基于条件变量阻塞 使用 pthread_cond_wait(3C) 可以以原子方式释放 mp 所指向的互斥锁,并导致调用线程基于 cv 所指向的条件变量阻塞。对于 Solaris 线程,请参见co...
  • a1232345
  • a1232345
  • 2015年01月27日 14:41
  • 531

单片机while(--t)延时计算(KEIL调试解读)

先贴上程序#include #define uchar unsigned char void Delay(uchar); //主程序 void main() { while(1) { ...
  • yhcfsr
  • yhcfsr
  • 2016年01月07日 11:09
  • 1391

单片机C语言中while(1)的问题

单片机C语言的主程序,通常要用一个while(1)语句来让程序进入一个无限循环,目的是为了让程序一直保持在我们需要运行的情况下。   虽然这种做法毋庸置疑,在网上还是有不少朋友有疑问,如果程序不加wh...
  • bytxl
  • bytxl
  • 2015年12月15日 17:21
  • 3012

互斥量、条件变量与pthread_cond_wait()函数的使用,详解(一)

1. 首先pthread_cond_wait 的定义是这样的 The pthread_cond_wait() and pthread_cond_timedwait() functions are...
  • cnclenovo
  • cnclenovo
  • 2015年03月24日 11:24
  • 845

Linux中posix线程的pthread_cond_wait函数为何使用while循环

关于pthread_cond_wait函数为何需要使用while循环,或者为何不使用if条件判断问题,经过Google后发现网上有不少已说明,这里给出自己的说明: 该函数的定义,可参考http://p...
  • sinat_15799399
  • sinat_15799399
  • 2015年01月06日 20:55
  • 1013
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:pthread_cond_wait()加一个while为什么的解释
举报原因:
原因补充:

(最多只允许输入30个字)