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

代码如下:

#include <pthread.h>
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总是成立。

pthread_cond_wait返回时无法保证判断式是真是假,因此需要重新判断。因此建议使用while循环进行验证,以便能够容忍这种竞争。

http://yaronspace.cn/blog/archives/1479

还有一种解释如下所示

http://bbs.csdn.net/topics/370094313

我猜应该是这个意思:
假设有两个线程(我就用伪代码了):
//thread 1
while(0<x<10)
    pthread_cond_wait(); //thread 2
while(5<x<15)
    pthread_cond_wait(); 如果某段时间内 x == 8,那么两个线程相继进入等待。 然后,另一个线程3:
修改x:x = 12
if(..) phtread_cond_signal() 那么,虽然线程1、2都被唤醒了,但是,此时线程1仍然不满足while,只有线程1跳出while,
我们假设一种情况线程2线获得了锁,然后发现满足循环条件,之后又有执行pthread_cond_wait()函数,然后阻塞在这儿,并且释放锁!
,pthread_cond_signal在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它被唤醒的线程就需要继续wait,while循环的意义就体现在这里了,而且规范要求pt   hread_cond_signal至少唤醒一个pthread_cond_wait上的线程,其实有些实现为了简单在单处理器上也会唤醒多个线程.
,某些应用,如线程池,pthread_cond_broadcast唤醒全部线程,但我们通常只需要一部分线程去做执行任务,所以其它的线程需要继续wait.所以强烈推荐此处使用while循环.
其实说白了很简单,就是pthread_cond_signal()也可能唤醒多个线程,而如果你同时只允许一个线程访问的话,就必须要使用while来进行条件判断,以保证临界区内只有一个线程在处理

关于pthread_cond_wait使用while循环判断的理解的更多相关文章

  1. Python条件循环判断

    1.条件判断语句 Python中条件选择语句的关键字为:if .elif .else这三个.其基本形式如下: 1 2 3 4 5 6 7 8 9 age_of_cc = 27   age = int( ...

  2. PHP循环语句深度理解分析——while, for, foreach, do while

    循环结构   一.while循环  while(表达式)  {   循环体;//反复执行,直到表达式为假  } 代码: $index = 1; while ($index<5) {        ...

  3. jquery for循环判断是否重复

    //使用for循环 判断是否有重名 var len=$("li").length;//获取页面中所有li的数量 for(var i=0; i<len; i++){ oldna ...

  4. R语言学习——循环判断语句

    循环  判断 函数 函数是一个对象,可以赋值 函数要放在调用函数的前面 输入输出 read.csv()------文本文件 csv是comma separated value的英文缩写,其读取逗号分隔 ...

  5. if循环判断

    if循环判断 if-else循环的语法格式 if 逻辑判断句: ​ 代码块 # 缩进表示所属关系 else 逻辑判断句: ​ 代码块 if 和elif同时使用来做多层判断 if 逻辑判断式: 代码块 ...

  6. JavaScript 循环判断练习题

    JavaScript 循环判断练习题 小明有一组水果("苹果","梨子","香蕉","葡萄","西瓜" ...

  7. Go语言循环判断的使用~

    Go 语言条件语句 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句. 下图展示了程序语言中条件语句的结 ...

  8. 重读APUE(15)-pthread_cond_wait与while循环

    即使pthead_cond_wait()和pthread_cond_timewait()没有错误返回,等待的条件也可能是假的:即使pthread_cond_timewait()返回了超时错误,关联的条 ...

  9. Spring的3级缓存和循环引用的理解

    此处是我自己的一个理解,防止以后忘记,如若那个地方理解不对,欢迎指出. 一.背景 在我们写代码的过程中一般会使用 @Autowired 来注入另外的一个对象,但有些时候发生了 循环依赖,但是我们的代码 ...

随机推荐

  1. 一般web典型的项目目录结构

    本文转自:http://blog.sina.com.cn/s/blog_4758a28b0100l3lp.html WebRoot-       -common   (系统框架公用jsp 如foote ...

  2. <转>字符编码笔记:ASCII,Unicode和UTF-8

    本文转自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 今天中午,我突然想搞清楚Unicode和UTF-8之间 ...

  3. C#三种定时器

    三个定时器分别是 实现按用户定义的时间间隔引发事件的计时器.此计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用. System.Windows.Forms.Timer 提供以指定的 ...

  4. Android学习系列(4)--App自适应draw9patch不失真背景

    做人要大度,海纳百川,做事要圆滑,左右逢源,这让我想到了编程也是如此,代码要扩展,界面也要考虑自适应.这篇文章是Android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用. 1. ...

  5. Python练习笔记——利用递归求年龄,第五个比第四个大2岁...

    现在有五个人, 第五个人比第四个人大两岁,18 第四个人比第三个人大两岁,16 第三个人比第二个人大两岁,14 第二个人比第一个人大两岁,12 第一个人现10岁,                 10 ...

  6. Python seed() 函数

    描述 seed() 方法改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数.. 语法 以下是 seed() 方法的语法: import random random.seed ( [x] ...

  7. eclipse引入的第三方jar包放到同一个目录下

    相信大家对这个不陌生吧: 使用eclipse,在JAVA项目中导入第三方jar包,然后看到一长串引入jar包信息,如下图: 看着不美观,也不是非常有必要,能不能像图中JRE System Librar ...

  8. SQL Server 2012 Express LocalDB 的作用

    微软最新推出的 SQL Server 2012 Express LocalDB 是一种 SQL Server Express 的运行模式,特别适合用在开发环境使用,也内置在 Visual Studio ...

  9. 使用xshell远程登录ubuntu使用vi编辑不能使用删除键方向键

    近期安装了xshell,远程登录上ubuntu后,在插入模式下,按删除键没有任何反应,按方向键分别打印出A.B.C.D,每个字符一行. 这是因为ubuntu初始化安装的是vi的tiny版本,解决办法安 ...

  10. cocos2dx 3.x fullPathForFilename及isFileExist在ios/mac下与win32下行为不同

    一,fullPathForFilename 项目先开发了ios/mac版本,这两天想把win32工程也配好,但遇到了部分资源无法正确找到的问题. 进一步观察发现,对于那些找不到的资源路径,fullPa ...