linux下线程的同步与互斥-条件变量

 

1.引入条件变量
         配合互斥锁一起使用(不能单独使用),用来控制多个线程对于共享资源的访问。
         当你使用互斥锁的时候,条件变量可以配合互斥锁实现满足某个条件的时候阻塞/解除阻塞某个线程。
         比如:举的例子中某个条件是指票的数量<=0
     条件变量有两个作用
         作用一:条件变量可以阻塞线程
         作用二:条件变量还可以唤醒(解除阻塞)线程
   2.相关的接口函数
         第一个:初始化条件变量
                pthread_cond_t 表示条件变量
                pthread_cond_t mycond;
                int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
                          参数: cond --》你要使用的条件变量
                                cond_attr --》条件的属性,一般设置为NULL,表示使用默认属性
         第二个:使用条件变量
                int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);  //阻塞线程
                          参数: cond --》你刚才定义初始化的那个条件变量
                                mutex --》你刚才定义的锁
                          注意重点:wait这个函数先解锁(做的第一件事情,防止死锁),然后在阻塞当前线程(做的第二件事情)
                int pthread_cond_signal(pthread_cond_t *cond);                       //唤醒一个线程
                          参数:cond --》你刚才定义初始化的那个条件变量
                          注意重点:signal这个函数先上锁(做的第一件事情),然后在唤醒当前线程(做的第二件事情) 
                int pthread_cond_broadcast(pthread_cond_t *cond);                    //唤醒所有阻塞在wait上的线程
                          参数:cond --》你刚才定义初始化的那个条件变量
                          注意重点:broadcast这个函数先上锁(做的第一件事情),然后在唤醒所有的线程(做的第二件事情)
          第三个:销毁条件变量
                int pthread_cond_destroy(pthread_cond_t *cond)

 多线程模拟售票,signal唤醒其中一个线程继续卖票

#include "myhead.h"

//定义全局变量表示当前放出来的票的数量
int num=15;

//定义锁变量
pthread_mutex_t mymutex;

//定义条件变量
pthread_cond_t mycond;

void *fun1(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mymutex);
		if(num<=0) //阻塞当前线程
		{
			printf("窗口1阻塞在wait了!\n");
			pthread_cond_wait(&mycond,&mymutex);
		}
		num--;
		printf("窗口1卖出一张票,还剩下 %d 张票!\n",num);
		sleep(1);
		pthread_mutex_unlock(&mymutex);
		usleep(100);
	}
}

void *fun2(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mymutex);
		if(num<=0) //阻塞当前线程
		{
			printf("窗口2阻塞在wait了!\n");
			pthread_cond_wait(&mycond,&mymutex);
		}
		num--;
		printf("窗口2卖出一张票,还剩下 %d 张票!\n",num);
		sleep(1);
		pthread_mutex_unlock(&mymutex);
		usleep(100);
	}
}

void *fun3(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mymutex);
		if(num<=0) //阻塞当前线程
		{
			printf("窗口3阻塞在wait了!\n");
			pthread_cond_wait(&mycond,&mymutex);
		}
		num--;
		printf("窗口3卖出一张票,还剩下 %d 张票!\n",num);
		sleep(1);
		pthread_mutex_unlock(&mymutex);
		usleep(100);
	}
}

void *fun4(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mymutex);
		if(num<=0) //阻塞当前线程
		{
			printf("窗口4阻塞在wait了!\n");
			pthread_cond_wait(&mycond,&mymutex);
		}
		num--;
		printf("窗口4卖出一张票,还剩下 %d 张票!\n",num);
		sleep(1);
		pthread_mutex_unlock(&mymutex);
		usleep(100);
	}
}

void *fun5(void *arg)
{
	while(1)
	{
		pthread_mutex_lock(&mymutex);
		if(num<=0) //阻塞当前线程
		{
			printf("窗口5阻塞在wait了!\n");
			pthread_cond_wait(&mycond,&mymutex);
		}
		num--;
		printf("窗口5卖出一张票,还剩下 %d 张票!\n",num);
		sleep(1);
		pthread_mutex_unlock(&mymutex);
		usleep(100);
	}
}

int main()
{
	pthread_t id1,id2,id3,id4,id5;
	
	//初始化锁
	pthread_mutex_init(&mymutex,NULL);
	
	//初始化条件变量
	pthread_cond_init(&mycond,NULL);
	
	//创建五个线程--》分别表示五个售票窗口
	pthread_create(&id1,NULL,fun1,NULL);
	pthread_create(&id2,NULL,fun2,NULL);
	pthread_create(&id3,NULL,fun3,NULL);
	pthread_create(&id4,NULL,fun4,NULL);
	pthread_create(&id5,NULL,fun5,NULL);
	
	//主函数代表铁道部,如果票卖完了,我从键盘输入数字表示新的票数
	while(1)
	{
		if(num<=0)
		{
			printf("铁道部领导,票卖完了,请求放票出来!\n");
			scanf("%d",&num);
			//唤醒其中一个线程,让它来卖票
			pthread_cond_signal(&mycond);
			//唤醒所有的线程,一起来卖票
			//pthread_cond_broadcast(&mycond);
		}
	}	
	
	//回收
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);
	pthread_join(id3,NULL);
	pthread_join(id4,NULL);
	pthread_join(id5,NULL);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值