多线程(18) pthread_cond_broadcast

本文详细解析了 pthread_cond_broadcast 和 pthread_cond_signal 的使用区别,通过具体示例对比了两者在不同场景下的行为表现,特别是针对多个线程等待同一条件变量时的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值