转自:http://www.xuebuyuan.com/2173853.html

pthread_cond_wait() 用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex

配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread_cond_signal()或pthread_cond_broadcast,把该线程唤醒,使pthread_cond_wait()通过(返回)时,该线程又自动获得该mutex。
  pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。
  使用pthread_cond_signal一般不会有“惊群现象”产生,他最多只给一个线程发信号。假如有多个线程正在阻塞等待着这个条件变量的话,那么是根据各等待线程优先级的高低确定哪个线程接收到信号开始继续执行。如果各线程优先级相同,则根据等待时间的长短来确定哪个线程获得信号。但无论如何一个pthread_cond_signal调用最多发信一次。
  但是pthread_cond_signal在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它被唤醒的线程就需要继续
wait,而且规范要求pthread_cond_signal至少唤醒一个pthread_cond_wait上的线程,其实有些实现为了简单在单处理器上也会唤醒多个线程. 
   另外,某些应用,如线程池,pthread_cond_broadcast唤醒全部线程,但我们通常只需要一部分线程去做执行任务,所以其它的线程需要继续wait.所以强烈推荐对pthread_cond_wait() 使用while循环来做条件判断.
以下就是一个来自MAN的示例
  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_broadcast(&cond);
              pthread_mutex_unlock(&mut);
pthread_cond_signal函数与条件变量的典型应用就是用来实现producer/consumer模型。
示例1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define BUFFER_SIZE 8
struct Products
{
int buffer[BUFFER_SIZE];
/*保证存取操作的原子性 互斥性*/
pthread_mutex_t locker;
/*是否可读*/           
pthread_cond_t notEmpty;
/*是否可写*/  
pthread_cond_t notFull;
int posReadFrom;
int posWriteTo;
};
int BufferIsFull(struct Products* products)
{
if ((products->posWriteTo + 1) % BUFFER_SIZE == products->posReadFrom)
{
return (1);
}
return (0);
}
int BufferIsEmpty(struct Products* products)
{
if (products->posWriteTo == products->posReadFrom)
{
return (1);
}
return (0);
}
/*制造产品*/。
void Produce(struct Products* products, int item)
{
/*原子操作*/
pthread_mutex_lock(&products->locker);
/*无空间可写入*/
while (BufferIsFull(products))
{
pthread_cond_wait(&products->notFull, &products->locker);
/*写入数据*/
products->buffer[products->posWriteTo] = item;
products->posWriteTo++;
if (products->posWriteTo >= BUFFER_SIZE)
products->posWriteTo = 0;
/*发信*/
pthread_cond_signal(&products->notEmpty);
/*解锁*/
pthread_mutex_unlock(&products->locker);
}
int Consume(struct Products* products)
{
int item;
pthread_mutex_lock(&products->locker);
/*为空时持续等待,无数据可读*/
while (BufferIsEmpty(products))
{
pthread_cond_wait(&products->notEmpty, &products->locker);
}
/*提取数据*/
item = products->buffer[products->posReadFrom];
products->posReadFrom++;
/*如果到末尾,从头读取*/
if (products->posReadFrom >= BUFFER_SIZE)
products->posReadFrom = 0;
pthread_cond_signal(&products->notFull); 
pthread_mutex_unlock(&products->locker);
return item;
}
#define END_FLAG (-1)
struct Products products;
void* ProducerThread(void* data)
{
int i;
for (i = 0; i < 16; ++i)
{
printf("producer: %d\n", i);
Produce(&products, i);
}
Produce(&products, END_FLAG);
return NULL;
}
void* ConsumerThread(void* data)
{
int item;
while (1)
{
item = Consume(&products);
if (END_FLAG == item)
       break;
printf("consumer: %d\n", item);
}
return (NULL);
}
int main(int argc, char* argv[])
{
pthread_t producer;
pthread_t consumer;
int result;
pthread_create(&producer, NULL, &ProducerThread, NULL);
pthread_create(&consumer, NULL, &ConsumerThread, NULL);
pthread_join(producer, (void *)&result);
pthread_join(consumer, (void *)&result);
exit(EXIT_SUCCESS);
}
示例2
pthread_cond_broadcast的是使用
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
pthread_mutex_t mymutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mymutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
void *mythread1(void *param)
{
printf("begin mythread1.\n");
pthread_mutex_lock(&mymutex1);
printf("wait in mythread1.\n");
pthread_cond_wait(&mycond,&mymutex1);
pthread_mutex_unlock(&mymutex1);
printf("end mythread1.\n");
return NULL;
}
void *mythread2(void *param)
{
printf("begin mythread2.\n");
pthread_mutex_lock(&mymutex2);
printf("wait in mythread2.\n");
pthread_cond_wait(&mycond,&mymutex2);
pthread_mutex_unlock(&mymutex2);
printf("end mythread2.\n");
return NULL;
}
int main(void)
{
printf("begin main thread.\n");
int i;
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,mythread1,NULL);
pthread_create(&tid2,NULL,mythread2,NULL);
sleep(5);
printf("try to wake up mythread1 and mythread2 in main thread.\n");
if(pthread_cond_broadcast(&mycond)){
printf("error\n");
return 1;
}
void *res;
pthread_join(tid1, &res);
pthread_join(tid2, &res);
printf("end main thread.\n");
return 0;
}
运行结果:
实例2
pthread_cond_broadcast的使用
  1. #include <pthread.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. pthread_mutex_t mymutex1 = PTHREAD_MUTEX_INITIALIZER;
  7. pthread_mutex_t mymutex2 = PTHREAD_MUTEX_INITIALIZER;
  8. pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
  9. void *mythread1(void *param)
  10. {
  11. printf("begin mythread1.\n");
  12. pthread_mutex_lock(&mymutex1);
  13. printf("wait in mythread1.\n");
  14. pthread_cond_wait(&mycond,&mymutex1);
  15. pthread_mutex_unlock(&mymutex1);
  16. printf("end mythread1.\n");
  17. return NULL;
  18. }
  19. void *mythread2(void *param)
  20. {
  21. printf("begin mythread2.\n");
  22. pthread_mutex_lock(&mymutex2);
  23. printf("wait in mythread2.\n");
  24. pthread_cond_wait(&mycond,&mymutex2);
  25. pthread_mutex_unlock(&mymutex2);
  26. printf("end mythread2.\n");
  27. return NULL;
  28. }
  29. int main(void)
  30. {
  31. printf("begin main thread.\n");
  32. int i;
  33. pthread_t tid1,tid2;
  34. pthread_create(&tid1,NULL,mythread1,NULL);
  35. pthread_create(&tid2,NULL,mythread2,NULL);
  36. sleep(2);
  37. printf("try to wake up mythread1 and mythread2 in main thread.\n");
  38. if(pthread_cond_broadcast(&mycond)){
  39. printf("error\n");
  40. return 1;
  41. }
  42. void *res;
  43. pthread_join(tid1, &res);
  44. pthread_join(tid2, &res);
  45. printf("end main thread.\n");
  46. return 0;
  47. }
运行结果:

begin main thread.

begin mythread1.

wait in mythread1.

begin mythread2.

wait in mythread2.

end mythread2.

try to wake up mythread1 and mythread2 in main thread.

end mythread1.

end main thread.

注意mythread2并真正的等待,它和我们的期望有所差别,似乎一个pthread_cond_t只能对应一个pthread_mutex_t
我们把以上代码稍作修正就可以了,具体见下面的实例3
实例3
  1. #include <pthread.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. pthread_mutex_t mymutex1 = PTHREAD_MUTEX_INITIALIZER;
  7. //pthread_mutex_t mymutex2 = PTHREAD_MUTEX_INITIALIZER;
  8. pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
  9. void *mythread1(void *param)
  10. {
  11. printf("begin mythread1.\n");
  12. pthread_mutex_lock(&mymutex1);
  13. printf("wait in mythread1.\n");
  14. pthread_cond_wait(&mycond,&mymutex1);
  15. pthread_mutex_unlock(&mymutex1);
  16. printf("end mythread1.\n");
  17. return NULL;
  18. }
  19. void *mythread2(void *param)
  20. {
  21. printf("begin mythread2.\n");
  22. pthread_mutex_lock(&mymutex1);
  23. printf("wait in mythread2.\n");
  24. pthread_cond_wait(&mycond,&mymutex1);
  25. pthread_mutex_unlock(&mymutex1);
  26. printf("end mythread2.\n");
  27. return NULL;
  28. }
  29. int main(void)
  30. {
  31. printf("begin main thread.\n");
  32. int i;
  33. pthread_t tid1,tid2;
  34. pthread_create(&tid1,NULL,mythread1,NULL);
  35. pthread_create(&tid2,NULL,mythread2,NULL);
  36. sleep(2);
  37. printf("try to wake up mythread1 and mythread2 in main thread.\n");
  38. if(pthread_cond_broadcast(&mycond)){
  39. printf("error\n");
  40. return 1;
  41. }
  42. void *res;
  43. pthread_join(tid1, &res);
  44. pthread_join(tid2, &res);
  45. printf("end main thread.\n");
  46. return 0;
  47. }
运行结果
123@xyy ~/gcc-test

$ gcc threadTest.c -o test.exe

123@xyy ~/gcc-test

$ ./test.exe

begin main thread.

begin mythread1.

wait in mythread1.

begin mythread2.

wait in mythread2.

try to wake up mythread1 and mythread2 in main thread.

end mythread1.

end mythread1.

end main thread.
该结果才是我们真正需要的。

结束!

pthread_cond_wait 详解的更多相关文章

  1. pthread_cond_signal与pthread_cond_wait详解

    转:http://blog.chinaunix.net/uid-11572501-id-3456343.html //pthread_cond_signal 只发信号,内部不会解锁,在Linux 线程 ...

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

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

  3. 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解

    Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解   多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...

  4. 通用线程:POSIX 线程详解,第 3 部分 条件互斥量(pthread_cond_t)

    使用条件变量提高效率 本文是 POSIX 线程三部曲系列的最后一部分,Daniel 将详细讨论如何使用条件变量.条件变量是 POSIX 线程结构,可以让您在遇到某些条件时“唤醒”线程.可以将它们看作是 ...

  5. 通用线程:POSIX 线程详解,第 3 部分

    通用线程:POSIX 线程详解,第 3 部分 使用条件变量提高效率 Daniel Robbins, 总裁兼 CEO, Gentoo Technologies, Inc. 简介: 本文是 POSIX 线 ...

  6. POSIX 线程详解(经典必看)

    http://www.cnblogs.com/sunminmin/p/4479952.html 总共三部分: 第一部分:POSIX 线程详解                               ...

  7. JUC中的AQS底层详细超详解

    摘要:当你使用java实现一个线程同步的对象时,一定会包含一个问题:你该如何保证多个线程访问该对象时,正确地进行阻塞等待,正确地被唤醒? 本文分享自华为云社区<JUC中的AQS底层详细超详解,剖 ...

  8. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  9. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

随机推荐

  1. 【算法】fhqtreap初探

    NOIP回来就一直想着学平衡树...平衡树写久了调不出来真的会头脑发热.jpg 大概只写了几道题... fhqtreap是不需要旋转的平衡树,仅使用分裂合并,一样可以保持平衡树的性质,并且可以非常简单 ...

  2. java深入探究16-mybatis

    链接:http://pan.baidu.com/s/1skJ4TNB 密码:koo9 1.引入mybatis jsbc简单易学,上手快,非常灵活构建SQL,效率高但代码繁琐,难以写出高质量的代码 hi ...

  3. HBase-存储-写路径

    写路径 当用户向HRegionServer发起put请求时,其会将请求交给对应的HRegion实例来处理.第一步是要决定数据是否需要写到由HLog类实现的预写日志中.WAL是标准的Hadoop Seq ...

  4. ztree高级实例(原创)

    最近项目中需要设计一个类似收藏夹的功能保存用户常用的东西,需要客户体验好,所以想到了以前用过的ztree. 在用ztree的过程中遇到一些问题,在此记录,提醒自己,也帮助遇到相同情况的同行们. 1.至 ...

  5. 循环插入一条数据的sql写法

    DECLARE @i INTSET @i = 1WHILE @i > 0 BEGIN DECLARE @TransportFormMstID BIGINT; DECLARE @TradeOrde ...

  6. Spring AOP的一个比喻和IOC的作用

    aop切面编程就是在常规的执行java类中方法前或执行后加入自定义的方法.比如你本来每天都去打酱油,去,打酱油,回.现在我每天在你打酱油路上等着,你去打酱油的时候我打你一顿,回来的时候给你点糖果吃.你 ...

  7. Centos Crontab查看状态和开启

    # service crond status crond is stopped # service crond start Starting crond # service crond status ...

  8. 利用虚拟网桥实现Docker容器的跨主机访问

    最近在研究Docker,Docker的网络配置是比较令人头疼的部分,尤其是跨主机的容器间通信,很多解决方案都比较复杂,这里,我只用虚拟网桥来实现Docker的跨主机访问,分享出来,希望对Docker学 ...

  9. openstack nova 基础知识——Quota(配额管理)

    一.什么是配额(quota)管理 简单的讲就是控制用户资源的数量.在openstack里,管理员为每一个工程(project)分配的资源都是有一定限制的,这些资源包括实例(instance).cpu. ...

  10. Token和session 详解

    Token的含义 原文链接 这只是一个思路 1.Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在 ...