pthread_cond_signal和pthread_cond_wait简介

来源:互联网 发布:软件测试个人总结 编辑:程序博客网 时间:2024/05/06 08:52
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
#include
#include
#include
 
#define BUFFER_SIZE8
 
struct Products
{
int buffer[BUFFER_SIZE];
/*保证存取操作的原子性 互斥性*/
pthread_mutex_t locker;
/*是否可读*/           
pthread_cond_t notEmpty;
/*是否可写*/  
pthread_cond_t notFull;
int posReadFrom;
int posWriteTo;
};
 
int BufferIsFull(structProducts*products)
{
if ((products->posWriteTo+ 1) % BUFFER_SIZE == products->posReadFrom)
{
return (1);
}
return (0);
}
 
int BufferIsEmpty(structProducts*products)
{
if (products->posWriteTo== products->posReadFrom)
{
return (1);
}
 
return (0);
}
 
/*制造产品*/
 
void Produce(structProducts*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(structProducts*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 <</span> 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(intargc, 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的是使用
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)
 {
pthread_mutex_lock(&mymutex1);
pthread_cond_wait(&mycond,&mymutex1);
fprintf(stderr,"this is mythread1.\n");
pthread_mutex_unlock(&mymutex1);
return NULL;
 }
 void *mythread2(void*param)
 {
pthread_mutex_lock(&mymutex2);
pthread_cond_wait(&mycond,&mymutex2);
fprintf(stderr,"this is mythread2.\n");
pthread_mutex_unlock(&mymutex2);
return NULL;
 }
 int main(intargc,char*argv[],char*envp[])
 {
int i;
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,mythread1,NULL);
pthread_create(&tid2,NULL,mythread2,NULL);
sleep(2)
if(pthread_cond_broadcast(&mycond)){
printf("error\n");
return 1;
  }
  void*res;
  pthread_join(tid1,&res);
  pthread_join(tid2,&res);
printf("this is main thread.\n");
return 0;
 }
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 办会员下款的口子 办了很多网贷征信会有影响吗 办征信在哪个银行 征信次数查的多不能办贷款吗 征信不好可以办车贷吗 办公司营业执照需要什么资料 办车险哪家保险公司好 办公司营业执照需要什么材料 教育咨询公司可以办辅导班吗 办公室里的女人 凶猛办公室播放 办公室恋情 办公室12.p 办公室图片 办公室英文 行政办公室 办公室纪实 办公室职责 办公室的 办公室图片真实 校长办公室 金三少 在办公室 总经理办公室 办公室的故事 办公室里 办公室工作 秘书办公室 办公室照片真实 办公室吊顶图片 办公室照片 学生会办公室 办公室英语怎么说 办公室英语 办公室简装 办公室价格 科技园办公室出租 企业办公室装修 200平米办公室装修 董事长办公室装饰 300平米办公室装修 老总办公室装修