多线程(18) pthread_cond_broadcast
1. pthread_cond_broadcast 唤醒所有被阻塞的线程
1.1 pthread_cond_broadcast 和 pthread_cond_signal
pthread_cond_broadcast(&cond1)的作用是唤醒所有正在pthread_cond_wait(&cond1,&mutex1)的线程。
pthread_cond_signal(&cond1)的的作用是唤醒所有正在pthread_cond_wait(&cond1,&mutex1)的至少一个线程。
(虽然我还没碰到过多于一个线程的情况,但是man帮组手册上说的是至少一个)
2. 代码例子说明
2.1 情况1:多个线程等待同一个cond,并且想对同一个mutex加锁。
2.1.1 使用 pthread_cond_signal 通知
代码:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#define SIGNAL 1
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
void* thread_task1(void* arg)
{
pthread_mutex_lock(&mutex1);
pthread_cond_wait(&cond,&mutex1);
printf("thread_task1 start working\n");
sleep(2);
printf("thread_task1 works over\n");
pthread_mutex_unlock(&mutex1);
return NULL;
}
void* thread_task2(void* arg)
{
pthread_mutex_lock(&mutex1);
pthread_cond_wait(&cond,&mutex1);
printf("thread_task2 start working\n");
sleep(2);
printf("thread_task2 works over\n");
pthread_mutex_unlock(&mutex1);
return NULL;
}
void* broadcastNotifyMutex(void* arg)
{
pthread_cond_broadcast(&cond);
return NULL;
}
void* signalNotifyMutex(void* arg)
{
pthread_cond_signal(&cond);
return NULL;
}
int main()
{
pthread_t thread_1,thread_2,thread_3;
pthread_create(&thread_1,NULL,thread_task1,NULL);
pthread_create(&thread_2,NULL,thread_task2,NULL);
sleep(2);
#ifdef SIGNAL
pthread_create(&thread_3,NULL,signalNotifyMutex,NULL);
#else
pthread_create(&thread_3,NULL,broadcastNotifyMutex,NULL);
#endif
pthread_join(thread_1,NULL);
pthread_join(thread_2,NULL);
pthread_join(thread_3,NULL);
return 0;
}
结果:
[root@localhost test]# gcc b1.c -pthread
[root@localhost test]# ./a.out
thread_task1 start working
thread_task1 works over
^C
[root@localhost test]#
2.1.2 使用 pthread_cond_broadcast 通知
代码:
将上面的代码 SIGNAL 注释掉即可
//#define SIGNAL 1
结果:
[root@localhost test]# ./a.out
thread_task1 start working
thread_task1 works over
thread_task2 start working
thread_task2 works over
[root@localhost test]#
2.1.3 分析:
当使用broadcast方式时,两个被阻塞的线程都被唤醒了,被唤醒的线程将变为pthread_mutex_lock(mutex1)的状态,他们将抢着对mutex1加锁,在本次运行过程中thread_1加锁成功了,thread_2没有成功抢到锁,于是它就被阻塞了,在thread_1执行完毕释放锁后,会通知所有被阻塞在mutex1上的线程,于是thread_2最终成功拿到了锁,然后顺利执行。
当使用signal方式时,thread_1和thread_2中只被唤醒了一个线程,在本次运行中是thread_1被唤醒了,而因为thread_2没有被唤醒,他就一直卡在pthread_cond_wait处呼呼大睡,所以最终只有thread_1执行完毕。
2.2 情况2:多个线程等待同一个cond,并且分别不同的mutex加锁。
2.2.1 使用 pthread_cond_signal 通知
代码:
将2.1.1代码添加并且thread_task2 中的 mutex1 修改为 mutex2。
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
结果:
[root@localhost test]# ./a.out
thread_task2 start working
thread_task2 works over
^C
[root@localhost test]#
2.2.2 使用 pthread_cond_broadcast 通知
代码:
将2.1.1代码添加并且thread_task2 中的 mutex1 修改为 mutex2。
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
并且将 SIGNAL 注释掉即可
//#define SIGNAL 1
结果:
[root@localhost test]# gcc b4.c -pthread
[root@localhost test]# ./a.out
thread_task1 start working
thread_task1 works over
thread_task2 start working
thread_task2 works over
[root@localhost test]#
2.2.3 分析:
当使用broadcast方式时,因为两个线程都被唤醒了,且它们想要加的锁并没有竞争关系,因此它们是并发执行的,而不必像前一种情况中那样必须一前一后执行。
当使用signal方式时,只被唤醒了一个线程,因此只有一个线程成功执行。
3.问题: 未解决,加printf 就不能通知
就是在 分别在 thread_task1 thread_task2 函数开头加下面打印,pthread_cond_broadcast 方式只有一个线程打印
printf(“111\n”);
printf(“222\n”);
参考
说明:参考代码中情况1的mutex写错了。
https://www.cnblogs.com/XiaoXiaoShuai-/p/11855408.html