理解线程互斥锁mutex引起的死锁

生活中的死锁场景

例子1

比如在现实生活中

有且仅有两个相邻的车位 分别命名为A B

这两个车位上分别停着两辆车 A车位停着车辆a B车位停着车辆b

现在 车辆a 车辆b 想要互换位置

但由于有且仅有两个车位 无法实现位置互换 (如果存在第三个空车位则可以实现)

车辆a想到B车位 但是B车位已经被车辆b占据了

车辆b想到A车位 但是A车位已经被车辆a占据了

例子2

有 甲乙丙丁 4个小朋友

甲 欠 乙10元

乙 欠 丙10元

丙 欠 丁10元

丁 欠 甲10元

这四个小朋友手里都没有钱

必须等待他人还钱 才能还给自己欠的人

因此 他们四个人永远处于等待中 无法实现还钱

程序中的死锁场景

资源1 资源2 是互斥性质的资源

同一时刻只能有一个线程使用

线程A需要先占用资源1 再占用资源2

线程B需要先占用资源2 再占用资源1

当线程A尝试占用资源2的时候 由于其已经被B占用 线程A进入阻塞

当线程B尝试占用资源1的时候 由于其已经被A占用 线程B进入阻塞

 Linux环境中代码如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>

//线程互斥量变量
//用互斥锁分别模拟对资源1和资源2的占用
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;

//线程A的处理函数
void *funA(void *arg)
{
	//线程A先占用资源1
	//再在占用资源1的情况下申请资源2
	pthread_mutex_lock(&mutex1);
	printf("线程A占用资源1\n");
	pthread_mutex_lock(&mutex2);	
	printf("线程A占用资源2\n");

	printf("线程A执行临界区代码\n");

	//解锁
	pthread_mutex_unlock(&mutex1);
	pthread_mutex_unlock(&mutex2);

	return NULL;
}

//线程B的处理函数
void *funB(void *arg)
{
	//线程B先占用资源2
	//再在占用资源2的情况下申请资源1
	pthread_mutex_lock(&mutex2);
	printf("线程B占用资源2\n");
	pthread_mutex_lock(&mutex1);
	printf("线程B占用资源1\n");

	printf("线程B执行临界区代码\n");

	//解锁
	pthread_mutex_unlock(&mutex2);
	pthread_mutex_unlock(&mutex1);

	return NULL;
}

int main(void)
{
	//获取函数的返回状态
	int ret = -1;
	//需要模拟线程A和线程B
	pthread_t tidA, tidB;

	//初始化互斥量
   	pthread_mutex_init(&mutex1, NULL);
   	pthread_mutex_init(&mutex2, NULL);

	//创建线程A和线程B
	pthread_create(&tidA, NULL, funA, NULL);
	pthread_create(&tidB, NULL, funB, NULL);

	//回收线程资源
	ret = pthread_join(tidA, NULL);
	if(0 != ret)
	{
		printf("pthread_join tidA failed\n");
		return 1;		
	}

	ret = pthread_join(tidB, NULL);
	if(0 !=ret)
	{
		printf("pthread_join tidB failed\n");
		return 1;
	}
	
	//销毁互斥量
	pthread_mutex_destroy(&mutex1);
	pthread_mutex_destroy(&mutex2);
	
	return 0;
}

运行效果 

多次执行 a.out

均未出现 "执行临界区代码" 的语句打印

这就意味着发生了死锁

在没有外界干扰的情况下 两个线程将永远阻塞

如何解决死锁场景

1.若长时间阻塞 释放已占用的资源后 再申请新的资源

2.一开始就一次性获取所有需要的资源

3.额外规定请求资源的顺序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

没伞的男孩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值