【多线程】死锁的发生与解决

本文探讨了死锁在多线程编程中的挑战,涉及交叉锁、内存限制、数据交互、数据库锁和文件锁等场景。通过死锁示例和诊断方法,提出了定时锁和公平竞争对象等避免死锁的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

死锁是在多线程处理任务中,比较有挑战性的问题。通常死锁的发生会随在服务不响应请求等其他情况。

在以下情况中可能会存在死锁:

  • 交叉锁导致死锁: 线程A持有X1锁等待X2锁、线程B持有X2等待X1锁。
  • 内存不足:当有两个线程,每一个线程都要获取30M内存来执行任务。线程A获取10M内存等待20M,线程B获取20M内存等待10M。
  • 一问一答式的数据交互:当客户端与服务端需要基于双方的回复时,如果客户端将请求发送后等待服务端响应,当因为网络原因无法给到服务端,服务端进行等待客户端发生。
  • 数据库锁:无论是数据库表级别的锁,还是行级别的锁,比如某一个线程执行for update语句退出了事务,其他线程访问该数据库是都将陷入死锁。
  • 文件锁:某一个线程获得到文件锁意外提出,其他读取该文件的线程也将会进入死锁知道系统释放文件句柄资源。
  • 死循环导致死锁:程序由于代码原因或者对某些一次处理不得当,进入了死循环。收入查询线程堆栈不会发现如何死锁现象,这个这种死锁一般称为系统假死,是一种最为致命的也是最难排查的死锁现象,进程对系统资源的使用量又达到了极限,想要做出dump也是比较困难。

死锁示例

/**
 * 测试死锁线程
 * 写一个基于交叉锁导致的死锁
 */
public class DeadLock {

    private  final  static  Object MUTEX_1 =new Object();
    private  final  static  Object MUTEX_2 =new Object();


    public  void  method1(){
        synchronized (MUTEX_1){
            System.out.println("已经获取MUTEX_1的monitor,尝试获取MUTEX_2");
            synchronized (MUTEX_2){
                System.out.println("获取MUTEX_2的monitor成功,开始执行任务");
            }
        }
    }
    public  void  method2(){
        synchronized (MUTEX_2){
            System.out.println("已经获取MUTEX_2的monitor,尝试获取MUTEX_1");
            synchronized (MUTEX_1){
                System.out.println("获取MUTEX_1的monitor成功,开始执行任务");
            }
        }
    }

    public static void main(String[] args) {
        DeadLock deadLock = new DeadLock();
        new Thread(()->{
            while (true){
                //循环等待
                deadLock.method1();
            }
        }).start();
        new Thread(()->{
            while (true){
                //循环等待
                deadLock.method2();
            }
        }).start();    
    }
}

死锁的诊断

我们大致知道死锁会在什么情况下发生后,我们可以借助一些工具来判断不同的情况下的死锁。

  • jstack 检查线程运行状态
  • jconsole 可视化线程状态
  • jvisualvm
  • jProfile

死锁的避免方案

  • 支持定时的锁:打破构成死锁条件的循环等待、不可剥夺原因。
  • 支持设置一个公平竞争对象,拿到该对象锁后就可以访问资源:打破构成死锁条件的资源互斥原因。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值