112

问答题 112 /413

请你说一下死锁的原因,以及如何打破,如何查看死锁进程状态

参考答案

参考回答:

1、死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。死锁的四个必要条件:

•    互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。

•    请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。

•    非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。

•    循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

java中产生死锁可能性的最根本原因是:1)是多个线程涉及到多个锁,这些锁存在着交叉,所以可能会导致了一个锁依赖的闭环;2)默认的锁申请操作是阻塞的。

如,线程在获得一个锁L1的情况下再去申请另外一个锁L2,也就是锁L1想要包含了锁L2,在获得了锁L1,并且没有释放锁L1的情况下,又去申请获得锁L2,这个是产生死锁的最根本原因。

2、避免死锁:

•    方案一:破坏死锁的循环等待条件。

•    方法二:破坏死锁的请求与保持条件,使用lock的特性,为获取锁操作设置超时时间。这样不会死锁(至少不会无尽的死锁)

•    方法三:设置一个条件遍历与一个锁关联。该方法只用一把锁,没有chopstick类,将竞争从对筷子的争夺转换成了对状态的判断。仅当左右邻座都没有进餐时才可以进餐。提升了并发度。

3、linux中查看死锁进程状态

使用pstack 和 gdb 工具对死锁程序进行分析

pstack 进程号 查看各个线程的堆栈信息

当进程吊死的时候,多次使用,死锁的线程将一直处于等锁的状态,确定某些线程一直没有变化,一直处于等锁的状态。那么这些线程很可能是死锁了。如果怀疑哪些线程发生死锁了,可以采用gdb 进一步attach线程并进行分析。

执行命令gdb attach 进程号,进入gdb调试终端

运行:(gdb) info thread