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_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 <</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(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的是使用
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(int
argc,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;
}