线程锁与避免线程锁 线程锁检测

进程是资源共享的,线程是资源私有的。

死锁的四个必要条件

在计算机专业的本科教材中,通常都会介绍死锁的四个必要条件。这四个条件缺一不可,或者说只要破坏了其中任何一个条件,死锁就不可能发生。我们来复习一下,这四个条件是:
•互斥(Mutual exclusion):存在这样一种资源,它在某个时刻只能被分配给一个执行绪(也称为线程)使用;
•持有(Hold and wait):当请求的资源已被占用从而导致执行绪阻塞时,资源占用者不但无需释放该资源,而且还可以继续请求更多资源;
•不可剥夺(No preemption):执行绪获得到的互斥资源不可被强行剥夺,换句话说,只有资源占用者自己才能释放资源;
•环形等待(Circular wait):若干执行绪以不同的次序获取互斥资源,从而形成环形等待的局面,想象在由多个执行绪组成的环形链中,每个执行绪都在等待下一个执行绪释放它持有的资源。

对于每个线程都需要得到最大资源才能工作的情况下,避免死锁有如下的一般编程实践

(1)请勿尝试在可能会对性能造成不良影响的长时间操作(如 I/O)中持有锁;

(2)请勿在可能直接或间接递归调用自己的函数里持有锁;

(3)一般情况下,请先使用粗粒度锁定方法,确定瓶颈,并在必要时添加细粒度锁定来缓解瓶颈。大多数锁定都是短期持有,而且很少出现争用。因此,请仅修复测得争用的那些锁定;

(4)使用多个锁定时,通过确保所有线程都按相同的顺序获取锁定来避免死锁;

(5)在等待某个资源时,使用超时机制;

(6)在系统中使用一个定时检查死锁环的机制,如果发现死锁就让一个线程的资源释放掉(数据库好像就是用这种方式)。

JDK自带了两个工具(jstack和JConsole),可以用来监测分析死锁的发生原因。

jstack工具用于生于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机每一条线程正在

执行的方法堆栈的集合,生成快照可以用于定位诸如线程死锁、死循环等问题。

  • 使用jstack工具导出线程堆栈信息(以Windows环境为例)

1.找到运行当前程序的JVM的进程id,命令及结果如下



2.运行jstack命令,并将结果信息导出来


3.使用文本编辑器打开刚导出的文本,只要查看最后关于死锁的堆栈信息即可


4.直接从堆栈信息不能直观得到结论,没关系,我们可以画图理清线程间的调度情况

(出现闭合环路,发生死锁)

原文地址:https://www.cnblogs.com/AmilyWilly/p/6163253.html