所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象
一.出现死锁的原因
(1)交叉锁可导致程序出现死锁
线程A持有R1的锁等待获取R2的锁,线程B持有R2的锁等待R1的锁,这种情况最容易导致程序发生死锁的问题
(2)内存不足
当并发请求系统可用内存时,如果此时系统内存不足,则可能会出现锁的情况。两个线程T1和T2,执行某个任务,其中T1已经获取了10MB内存,T2获取了20MB内存,如果每个线程的执行单元都需要30MB的内存,但是剩余可用的 内存刚好是20MB,那么两个线程有可能都在等待彼此能够释放内存资源
(3)一问一答式的数据交换
服务端开启某个端口,等待客户端访问,客户端发送请求立即等待接收,由于某种原因服务端错过了客户端的请求,仍然在等待一问一答的数据交互,此时服务端和客户端都在等待对方发送数据。
(4)数据库锁
无论是数据库表级别的锁,还是行级别的锁,比如某个线程执行for update语句退出了事物,其它此案成访问该数据库都将陷入死锁
(5)文件锁
某线程获得文件锁意外退出,其它读取该文件的线程也将进入死锁直到系统释放文件句柄资源
(6)死循环引起的死锁
程序由于代码原因或者某些异常处理不当,进入死循环,虽然查看堆栈信息不会出现任何死锁的迹象,但是程序不工作,CPU占有率居高不下,这种死锁被称为系统假死
二、交叉死锁举例
package 死锁; public class DeadLock { private final Object READ = new Object(); private final Object WRITE = new Object(); public void read() { synchronized(READ) { System.out.println(Thread.currentThread().getName()+" get READ lock"); synchronized(WRITE) { System.out.println(Thread.currentThread().getName()+" get WRITE lock"); } System.out.println(Thread.currentThread().getName()+" release WRITE lock"); } System.out.println(Thread.currentThread().getName()+" release READ lock"); } public void write() { synchronized(WRITE) { System.out.println(Thread.currentThread().getName()+" get WRITE lock"); synchronized(READ) { System.out.println(Thread.currentThread().getName()+" get READ lock"); } System.out.println(Thread.currentThread().getName()+" release READ lock"); } System.out.println(Thread.currentThread().getName()+" release WRITE lock"); } public static void main(String[] args) { final DeadLock deadLock = new DeadLock(); new Thread(new Runnable() { @Override public void run() { while(true) { deadLock.read(); } } },"READ-THREAD").start(); new Thread(new Runnable() { @Override public void run() { while(true) { deadLock.write(); } } },"WRITE-THREAD").start(); } }
三、交叉锁引起的死锁诊断
运行DeadLock,程序将陷入死锁,打开jstack或者jconsole工具,Jstack-l PID会直接发现死锁的信息
一般交叉死锁引起的锁线程都会是BLOCKED状态,CPU占用资源不高,很容易借助工具来发现
说明:摘自《JAVA高并发编程详解-多线程与架构设计》
链接:https://pan.baidu.com/s/1BHH2X0lCt2xGz-U7ryTbIA
提取码:qx40
来源:https://www.cnblogs.com/lpfalpd/p/10880250.html