通常,和pthread _cond_wait 配对使用的有pthread_cond_signal , 同时还有用于pthread_cond_t初始化的pthread_cond_init,销毁的pthread_cond_destroy函数,还有用于加锁保护的pthread_mutex_lock和pthread_mutex_unlock,稍后会对为什么进行加锁做解释。

初始化条件变量int pthread_cond_init(pthread_cond_t *cv, pthread_cond_attr *cattr);

函数返回值:返回0表示成功,其他都表示失败。对于函数的参数:pthread_cond_attr 是用来设置pthread_cond_t的属性,当传入的值是NULL的时候表示使用默认的属性。这个函数返回时,创建的条件变量保存在cv所指向的内存中。可以用宏PTHREAD_COND_INITIALIZER来初始化条件变量。但是请记住不能用多个线程初始化同一个条件变量,当一个线程要使用条件变量的时候确保它是未被使用的。

条件变量的销毁:int pthread_cond_destroy(pthread_cond_t *cv); 返回0表示成功,返回其他值都表示失败。

条件变量的使用: int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)以及 int pthread_cond_signal(pthread_cond_t *cv);

使用pthread_cond_wait方式如下:

while (1) {pthread _mutex_lock(&mutex)while或if(条件NOT成立)pthread_cond_wait(&cond, &mutex);执行 do sthpthread_mutex_unlock(&mutex);
}

需要解释的有两点,为什么要加锁,以及为什么可以使用while和if。首先解释第一点,有两个方面,线程在执行的部分访问的是进程的资源,有可能有多个线程需要访问它,为了避免由于线程并发执行所引起的资源竞争,所以要让每个线程互斥的访问公有资源,但是细心一下就会发现,如果while或者if判断的时候,不满足线程的执行条件,那么线程便会调用pthread_cond_wait阻塞自己,但是它持有的锁怎么办呢,如果他不归还操作系统,那么其他线程将会无法访问公有资源。这就要追究一下pthread_cond_wait的内部实现机制,当pthread_cond_wait被调用线程阻塞的时候,pthread_cond_wait会自动释放互斥锁。释放互斥锁的时机是什么呢:是线程从调用pthread_cond_wait到操作系统把他放在线程等待队列之后,这样做有一个很重要的原因,就是mutex的第二个作用,保护条件。想一想,线程是并发执行的,如果在没有把被阻塞的线程A放在等待队列之前,就释放了互斥锁,这就意味着其他线程比如线程B可以获得互斥锁去访问公有资源,这时候线程A所等待的条件改变了,但是它没有被放在等待队列上,导致A忽略了等待条件被满足的信号。倘若在线程A调用pthread_cond_wait开始,到把A放在等待队列的过程中,都持有互斥锁,其他线程无法得到互斥锁,就不能改变公有资源。这就保证了线程A被放在等待队列上之后才会有公有资源被改变的信号传递给等待队列。对于这点apue给出的解释:The mutex passed to pthread_cond_wait protects the condition.The caller passes it locked to the function, which then atomically places the calling thread on

the list of threads waiting for the condition and unlocks the mutex. This closes the window between the time that the condition is checked and the time that the

thread goes to sleep waiting for the condition to change, so that the thread doesn't miss a change in the condition. When pthread_cond_wait returns,

the mutex is again locked.

接下来讲解使用while和if判断线程执行条件是否成立的区别。一般来说,在多线程资源竞争的时候,在一个使用资源的线程里面(消费者)判断资源是否可用,不可用便调用pthread_cond_wait,在另一个线程里面(生产者)如果判断资源可用的话,则调用pthread_cond_signal发送一个资源可用信号。但是在wait成功之后,资源就一定可以被使用么,答案是否定的,如果同时有两个或者两个以上的线程正在等待此资源,wait返回后,资源可能已经被使用了,在这种情况下,应该使用:

while(resource == FALSE)

pthread_cond_wait(&cond, &mutex);

如果之后一个消费者,那么使用if就可以了。解释一下原因,分解pthread_cond_wait的动作为以下几步:

1,线程放在等待队列上,解锁

2,等待 pthread_cond_signal或者pthread_cond_broadcast信号之后去竞争锁

3,若竞争到互斥索则加锁。

上面讲到,有可能多个线程在等待这个资源可用的信号,信号发出后只有一个资源可用,但是有A,B两个线程都在等待,B比较速度快,获得互斥锁,然后加锁,消耗资源,然后解锁,之后A获得互斥锁,但他回去发现资源已经被使用了,它便有两个选择,一个是去访问不存在的资源,另一个就是继续等待,那么继续等待下去的条件就是使用while,要不然使用if的话pthread_cond_wait返回后,就会顺序执行下去。

下面来讲一下:pthread_cond_wait和pthread_cond_singal是怎样配对使用的:

     等待线程:

pthread_cond_wait前要先加锁
     pthread_cond_wait内部会解锁,然后等待条件变量被其它线程激活
     pthread_cond_wait被激活后会再自动加锁

     激活线程:
     加锁(和等待线程用同一个锁)
     pthread_cond_signal发送信号
     解锁
     激活线程的上面三个操作在运行时间上都在等待线程的pthread_cond_wait函数内部。

#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  cond  = PTHREAD_COND_INITIALIZER;int count = 0;void *decrement(void *arg) {printf("in derement.\n");pthread_mutex_lock(&mutex);if (count == 0)pthread_cond_wait(&cond, &mutex);count--;printf("----decrement:%d.\n", count);printf("out decrement.\n");pthread_mutex_unlock(&mutex);return NULL;
}void *increment(void *arg) {printf("in increment.\n");pthread_mutex_lock(&mutex);count++;printf("----increment:%d.\n", count);if (count != 0)pthread_cond_signal(&cond);printf("out increment.\n");pthread_mutex_unlock(&mutex);return NULL;
}int main(int argc, char *argv[]) {pthread_t tid_in, tid_de;pthread_create(&tid_de, NULL, (void*)decrement, NULL);sleep(2);pthread_create(&tid_in, NULL, (void*)increment, NULL);sleep(5);pthread_join(tid_de, NULL);pthread_join(tid_in, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

这个例子中, decrement函数中也可以使用while,读者可以换一下试试。
然后在给出一个生产者消费者的例子:

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>typedef struct node_s {int data;struct node_s *next;
}node_t;node_t *head = NULL;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition = PTHREAD_COND_INITIALIZER;void cleanup_handler(void *arg) {printf("cleanup_handler is running.\n");free(arg);pthread_mutex_unlock(&mutex);
}void *thread_func(void *arg) {node_t *p = NULL;pthread_cleanup_push(cleanup_handler, p);while (1) {pthread_mutex_lock(&mutex);while (NULL == head)pthread_cond_wait(&condition, &mutex);p = head;head = head->next;printf("process %d node.\n", p->data);free(p);pthread_mutex_unlock(&mutex);}pthread_cleanup_pop(0);return NULL;
}int main(int argc, char *argv[]) {pthread_t tid;node_t *temp = NULL;int i;pthread_create(&tid, NULL, (void*)thread_func, NULL);for (i = 0; i < 10; i++) {temp = (node_t*)malloc(sizeof(node_t));temp->data = i;pthread_mutex_lock(&mutex);temp->next = head;head = temp;pthread_cond_signal(&condition);pthread_mutex_unlock(&mutex);sleep(1);}pthread_cancel(tid);pthread_join(tid, NULL);return 0;
}

其中的 pthread _cleanup_push  和 pthread_cleanup_pop,pthread_cancel作为下次博客讲解的内容。
————————————————
原文链接:https://blog.csdn.net/zzran/article/details/8830213


pthread_cond_broadcast用处

以前学习POSIX THREAD时就不太理解broadcast在什么场景下使用比较合适。因为broadcast的语义是唤醒所有被阻塞的线程。

当时的想法是,在系统析构时调用它比较有效,唤醒阻塞的线程,回收线程资源,然后退出系统。

今天在做 lock_server 时,才了解到broadcast的用处,它的效果是,减少系统中条件变量的个数

需求

系统中有很多锁,锁有FREE和LOCKED两种状态。不同的client会申请自己需要的锁,server响应client的申请。假如client申请的锁已被占用,那么client应该阻塞,等待锁被释放。

设计1

client阻塞在它需要的那个锁上,应该是pthread_cond_wait(&lockid, &mutex)

这样设计的话,对于每一个锁,都需要一个对应的条件变量,这样设计增加了系统的复杂性

设计2 应用broadcast

系统中设置一个共享的条件变量 cond,所有的线程阻塞在cond上

1

2

3

4

while(lock_status_[lid] == LOCKED) {

    pthread_cond_wait(&c_, &m_);

}  

    pthread_cond_broadcast(&c_);   

这样,一旦某个锁被释放,所有的阻塞线程都会被唤醒,但唯有阻塞在这个锁的线程才能真正被唤醒。

另外,mutex的使用,保证了最多一个线程被真正唤醒,即便是broadcast。

pthread_cond_wait pthread_cond_broadcast相关推荐

  1. 操作系统:Linux进程与线程

    这里是一部分内容,还会做修改. 一:目的及内容 学习fork(),exec,pthread库函数的使用,阅读源码,分析fork,exec,pthread_create函数的机理 代码实现: 进程A创建 ...

  2. PulseAudio多线程通信:pthread_cond_broadcast/pthread_cond_signal/pthread_cond_wait(九)

    pthread_cond_broadcast() pthread_cond_signal() pthread_cond_wait()函数用法概述1.pthread_cond_wait() 用于阻塞当前 ...

  3. pthread_cond_wait()函数的详解

    http://hi.baidu.com/tjuer/item/253cc6d66b921317d90e4483 了解 pthread_cond_wait() 的作用非常重要 -- 它是 POSIX 线 ...

  4. 条件变量 pthread_cond_wait

    1.先了解一下等待队列.(默认大家了解mutex,如果不了解:https://blog.csdn.net/qq_33890670/article/details/79967231) 等待队列,是指li ...

  5. pthread_cond_wait() 函数的使用

    1. 首先pthread_cond_wait 的定义是这样的 The pthread_cond_wait() and pthread_cond_timedwait() functions are us ...

  6. 条件变量pthread_cond_wait()和pthread_cond_signal()详解

    条件变量          条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立&qu ...

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

    等号上面这段是大多数网上给pthread_cond_wait()加一个while为什么的解释:但是有些地方不太明白或者说没有解释清晰: 准备:1:pthread_cond_singal是唤醒至少一个线 ...

  8. pthread_cond_broadcast相关

    参考:http://blog.csdn.net/cupidove/article/details/9331859 pthread_cond_timedwait()函数阻塞住调用该函数的线程,等待由co ...

  9. 深入理解pthread_cond_wait、pthread_cond_signal

    ===============================man pthread_cond_wait的解释========================== LINUX环境下多线程编程肯定会遇到 ...

最新文章

  1. SQL压力测试用的语句和相关计数器
  2. 面试腾讯算法:组合总和
  3. 工作中用到的设计模式?
  4. Linq to sql 消除列重复 去重复
  5. vue-cli生成项目时你应当知道的
  6. CoffeeScript 1.9发布,引入对生成器的支持
  7. .Net Attribute特性
  8. 显示visual studio试用版序列号输入框小程序_Visual Studio 2008试用版的评估期已经结束 的解决方法...
  9. 开源项目: FlycoTabLayout SlidingTabLayout不显示字体的问题
  10. codeforces每日5题(均1500)-第十七天
  11. Adobe Acrobat XI 一进去就闪退;解决Acrobat的闪退问题
  12. MySql 指定某一字段排在前面
  13. 入过滤(Ingress Filtering)
  14. 2013应届毕业生各大IT公司待遇整理汇总篇(转)
  15. 深入理解anchor
  16. IE8下载的文件放在哪
  17. OpenCV-python利用蒙版进行叠加(含alpha通道)
  18. 捷联惯导系统学习4.1(惯导数值更新算法)
  19. 用Python实现自动刷王者荣耀金币,这简直不要太爽了
  20. 如何在 Mac 上将 PDF 转换为 Word [6 种免费方法]

热门文章

  1. 想方便快捷的分享/收藏图片?试试免费好用的微博/b站图床
  2. 数据结构考研:大O表示法最浅显易懂且详细深入的解释及与小o表示法的区别(十分钟必懂)
  3. 读《拆掉思维的墙》小记
  4. signature=32d532a97f37c02b1149992578cf4af9,~(11)C-CFT PET功能显像Parkin基因缺陷少年型帕金森病患者脑多巴胺转运体...
  5. 2021年机修钳工(中级)考试题库及机修钳工(中级)试题解析
  6. SMAA算法详解 - SMAANeighborhoodBlendingVS
  7. JavaScript常见面试题
  8. 博弈论--耶鲁大学公开课
  9. springboot基于vue众筹平台系统
  10. C++ 简易的五子棋游戏 初学者