pthread_cond_signal 和 pthread_cond_wait 简介

  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的使用

#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(2);
    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;
}  

运行结果:

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

#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(&mymutex1);
    printf("wait in mythread2.\n");
    pthread_cond_wait(&mycond,&mymutex1);
    pthread_mutex_unlock(&mymutex1);
    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(2);
    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;
}  

运行结果

[email protected] ~/gcc-test
$ gcc threadTest.c -o test.exe
[email protected] ~/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.

该结果才是我们真正需要的。

时间: 2024-10-27 05:17:34

pthread_cond_signal 和 pthread_cond_wait 简介的相关文章

pthread_cond_signal与pthread_cond_wait

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_

pthread_cond_signal与pthread_cond_wait详解

转:http://blog.chinaunix.net/uid-11572501-id-3456343.html //pthread_cond_signal 只发信号,内部不会解锁,在Linux 线程中,有两个队列,分别是cond_wait队列和mutex_lock队列, cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用返回到用户空间,不会有性能的损耗.(pthread_cond_signal unlock后pthread_cond_wait才能上锁)

计算机科学精彩帖子收集

inux源码 LXR 源自"the Linux Cross Referencer",中间的"X"形象地代表了"Cross".与 Source Navigator 类似,它也是分析阅读源代码的好工具.不同的是,它将源代码借助浏览器展示出来,文件间的跳转过程成了我熟悉的点击超链接动作. http://lxr.linux.no/   LXR安装过程简介 linux手册 http://linux.die.net/man/ Linux每周新闻 http:/

关于 pthread_cond_wait 和 pthread_cond_signal , signal 无效的问题

关于一个消费者模式,,,引起的问题.. 我在io线程里不断的把一个函数调用放到队列里 然后ruby线程就不断的从这个队列里取出函数之争并执行. 典型的 消费者模式. 我以前以为是这样... 这是work线程 pthread_mutex_lock(&mutex2) while(( invoke = get_invoke() ) != NULL){ do_invoke(invoke); } pthread_mutex_unlock(&mutex2) pthread_cond_wait(&

pthread_cond_wait、pthread_cond_signal 不深入的思考

编程中,当涉及到多个线程需要访问同一个全局对象时,往往需要进行线程同步,而线程同步,往往是一个约定俗成的东西.比如说: 1 //*.cpp 2 int g_var ; pthread_mutex_t g_mtx ; 3 static void * threadFunc(void * Par) { 4 pthread_mutex_lock(&g_mtx) ; 5 6 g_var = //some value ; 7 8 return NULL ; 9 } 为了保持g_var的一致性,理应在所有线程

pthread_cond_signal 和 pthread_mutex_unlock顺序问题

pthread_cond_signal()的具体位置? "pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间, " 我认为这个做法有个问题,举个例子 简单假设线程1.2,curnum 值为 1, 语句执行顺序如下: T2-->;pthread_mutex_lock(&mutex_curnum); T2-->;while(curnum) T2-->; pthread_

互斥锁和条件变量的结合使用

互斥锁一个明显的缺点是他只有两种状态:锁定和非锁定.而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,他常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程.这些线程将重新锁定互斥锁并重新测试条件是否满足.一般说来,条件变量被用来进行线承间的同步. 对于条件锁,通常配合一个互斥锁一起使用,以防止多个线程同时请求pt

线程条件量使用注意事项

pthread_cond_wait的使用: pthread_mutex_t qlock; pthread_cond_t qready: /************pthread_cond_wait()的使用方法**********/ pthread_mutex_lock(&qlock); /*lock*/ //等待某资源,并以qready作为条件通知我们 while (condition == FALSE){ pthread_cond_wait(&qready, &qlock);

posix thread介绍

 posix thread是操作系统级(OS level)的API规范,主要用来定义线程及线程间同步的相关操作,采用C语言定义.posix规范主要在unix like类系统上实现:Windows类系统采用了自己的线程API.目前很多语言都在其标准库中提供了语言级的线程支持:如Java中的Thread,concurrenty包:python中的threading model:C++11标准中的thread库等.还有很多以第三方库方式提供的各种语言的线程实现,就不一一列举了. 线程环境要素 定义