线程安全之死锁

目录

一、概念

二、例子

三、死锁相关面试题目


一、概念

死锁主要发生在有多个依赖锁存在时,会在一个线程试图以另一个线程相反顺序锁住互斥量时发生

死锁使得一个或多个线程被挂起而无法继续执行,最糟糕的是,这种情况还不容易被发现。

在一个线程中对一个已经加锁的普通锁再次加锁,将导致死锁

这种情况可能出现在设计得不够仔细地递归函数中。

另外,如果两个线程按照不同的顺序来申请两个互斥锁,也容易发生死锁

二、例子

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>

int a=0;
int b=0;
pthread_mutex_t mutex_a;
pthread_mutex_t mutex_b;
void *another(void *arg)
{
	pthread_mutex_lock(&mutex_b);
	printf("in child thread,got mutex b,waiting for mutex a\n");
	sleep(5);
	++b;
	pthread_mutex_lock(&mutex_a);
	b+=a++;
	pthread_mutex_unlock(&mutex_a);
	pthread_mutex_unlock(&mutex_b);
	pthread_exit(NULL);
}

int main()
{
	pthread_t id;
	pthread_mutex_init(&mutex_a,NULL);
	pthread_mutex_init(&mutex_b,NULL);
	pthread_create(&id,NULL,another,NULL);

	pthread_mutex_lock(&mutex_a);
	printf("in parent thread,got mutex a,waiting for mutex b\n");
	sleep(5);
	++a;
	pthread_mutex_lock(&mutex_b);
	a+=b++;
	pthread_mutex_unlock(&mutex_b);
	pthread_mutex_unlock(&mutex_a);
	
	pthread_join(id,NULL);
	pthread_mutex_destroy(&mutex_a);
	pthread_mutex_destroy(&mutex_b);
	exit(0);
}

主线程试图先占有互斥锁mutex_a,然后操作被该锁保护的变量a,但操作完毕之后,主线程并没有立即释放互斥锁mutex_a,而是又申请互斥锁mutex b,并在两个互斥锁的保护下,操作变量a和b,最后才一起释放这两个互斥锁;

于此同时,子线程则按照相反的顺序来申请互斥锁mutex_a和mutex_b,并在两个锁的保护下操作变量a和b;

我们用sleep函数来模拟连续两次调用pthread_mutex_lock之间的时间差,以确保代码中的两个线程各自先占用一个互斥锁(主线程占有mutex_a,子线程占有mutex_b),然后等待另外一个互斥锁(主线程等待mutex_b,子线程等待mutex_a).这样,两个线程就僵持住了,谁也不能继续往下执行,从而形成死锁.

如果代码中不加入sleep函数,则这段代码或许总能成功地运行,从而为程序留下了一个潜在地bug.

如何避免死锁是使用互斥量应该格外注意的东西

  • 总体来讲,有几个不成文的基本规则:
  • 对共享资源操作前一定要获得锁;
  • 完成操作以后一定要释放锁;
  • 尽量短时间地占用锁;
  • 如果有多个锁,如获得顺序是ABC连环扣.释放顺序也应该是ABC;
  • 线程错误返回时应该释放它所获得的锁;

三、死锁相关面试题目

问题:如何避免死锁?
解答:
死锁的概念:多个进程或线程访问一组竟态资源的时候,出现的永久阻塞的问题。也可以这么说:指两个或两个以上的线程或进程在执行程序的过程中,因争夺资源或者程序推进顺序不当而相互等待的一个现象。
产生的原因主要有三个:系统资源不足,程序运行推进的顺序不当,资源分配不当。

或者说:死锁产生的必要条件是:

  • 互斥条件
  • 请求和保持条件
  • 不剥夺条件
  • 环路等待条件

避免死锁就是打破这四个条件中的某一个即可。如某个进程申请多个资源,只要有一个资源不满足暂时就不要分配任何资源。等所有资源能满足时一起分配。
处理死锁的基本方法?

  • 预防死锁
  • 避免死锁(银行家算法)
  • 检测死锁(资源分配)
  • 解除死锁:剥夺资源、撤销进程
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值