pthread_cond_broadcast() pthread_cond_signal() pthread_cond_wait()函数用法概述
1.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。
2.pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状
态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。
使用pthread_cond_signal一般不会有“惊群现象”产生,他最多只给一个线程发信号。假如有多个线程正在阻
塞等待着这个条件变量的话,那么是根据各等待线程优先级的高低确定哪个线程接收到信号开始继续执行。如果各
线程优先级相同,则根据等待时间的长短来确定哪个线程获得信号。但无论如何一个pthread_cond_signal调用
最多发信一次。
但是pthread_cond_signal在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它
被唤醒的线程就需要继续 wait,而且规范要求pthread_cond_signal至少唤醒一个pthread_cond_wait上的线
程,其实有些实现为了简单在单处理器上也会唤醒多个线程.
3.如线程池,pthread_cond_broadcast唤醒全部线程,但我们通常只需要一部分线程去做执
行任务,所以其它的线程需要继续wait.所以强烈推荐对pthread_cond_wait() 使用while循环来做条件判断.
1.适用pthread_cond_broadcast
1.一个生产者多消费者,生产者能一次产生多个产品的情况。
2.多生产者多消费者
3.读写锁实现(写入之后,通知所有读者)
//test.c
#include
#include
#include
#define MAX_THREAD_NUM 5
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* thread_fun(void* arg)
{
int index = *(int*)arg;
printf("[%d]thread start up!\n", index);
pthread_mutex_lock(&mutex);
printf("[%d]thread wait...\n", index);
pthread_cond_wait(&cond, &mutex);
printf("[%d]thread wake up\n", index);
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}
int main()
{
pthread_t tid[MAX_THREAD_NUM];
for(int i = 0; i < MAX_THREAD_NUM; i++)
{
pthread_create(&tid[i], NULL, thread_fun, &i);
sleep(1);
}
sleep(3);
//pthread_cond_signal(&cond); //唤醒N个线程中的一个
pthread_cond_broadcast(&cond); //全部唤醒
for(int i = 0; i < MAX_THREAD_NUM; ++i)
{
pthread_join(tid[i], NULL);
}
return 0;
}
pthread_cond_signal只能唤醒N个线程中的一个,而pthread_cond_broadcast可以唤醒全部的N个线程。
2.适用pthread_cond_signal的情况
pthread_cond_signal()函数作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。
1.单一生产者,生产者一次生产一个产品的情况,最好一个消费者
2.注意:pthread_cond_signal在单一异步唤醒的处理线程的情况时,是不安全的
//伪代码
pthread_mutex_t mul;
pthread_cond_t cond;
pthread_mutex_lock(&mul); //加锁
/***
执行对数据的操作
****/
pthread_cond_signal(&cond); //唤醒基于cond条件的其他阻塞线程
pthread_mutex_unlock(&mul); //解锁
//pthread_cond_signal()唤醒pthread_cond_wait()用法
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//初始化互斥锁
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//初始化条件变量
int i=1;
void *thread1(void *junk)
{
for(i=1;i<=6;i++){
pthread_mutex_lock(&mutex);//锁住互斥量; mutex:0xcda5f700 -> 0
printf("thread1: lock line = %d, i = %d, i / 3 = %d\n", __LINE__,i,i % 3);
if(i % 3 == 0){
printf("thread1:signal before, line = %d, cond = %#x\n", __LINE__,cond);
//线程1的cond条件改变,通知线程2
pthread_cond_signal(&cond);//条件改变,发送信号,通知t_b进程
printf("thread1:signal after, line = %d, cond = %#x\n", __LINE__,cond);
sleep(1);
}
pthread_mutex_unlock(&mutex);//解锁互斥量
printf("thread1: unlock line = %d\n\n", __LINE__);
sleep(1);
}
}
void *thread2(void *junk){
while(i<6)
{
pthread_mutex_lock(&mutex);//mutex:0xcda5f700 -> 0
printf("thread2: lock line = %d, i = %d, i / 3 = %d\n", __LINE__,i,i%3);
if(i % 3 != 0){
printf("thread2: wait before, line = %d, cond = %#x\n", __LINE__,cond);
//线程2阻塞,等待线程1唤醒
pthread_cond_wait(&cond,&mutex);//解锁mutex,并等待cond改变,等待pthread_cond_signal()唤醒
printf("thread2: wait after, line = %d, %#x\n", __LINE__,cond);
}
pthread_mutex_unlock(&mutex);
printf("thread2: unlock line = %d\n\n", __LINE__);
sleep(1);
}
}
int main(void){
pthread_t t_a;
pthread_t t_b;
pthread_create(&t_a,NULL,thread1,(void *)NULL);//创建进程t_a
pthread_create(&t_b,NULL,thread2,(void *)NULL); //创建进程t_b
pthread_join(t_a, NULL);//等待进程t_a结束
pthread_join(t_b, NULL);//等待进程t_b结束
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
3. pthread_cond_wait()函数
pthread_cond_signal()函数在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它被唤醒的线程就需要继续 wait.
//伪代码
pthread_mutex_t mul;
pthread_cond_t cond;
pthread_mutex_lock(&mul); //加锁
while(condition){
pthread_cond_wait(&cond,&mul); //如果condition不满足,才会执行数据操作
}
/***
执行对数据的操作
****/
pthread_mutex_unlock(&mul); //解锁