java 线程——死锁

两个或者两个以上的线程在执行过程中由于竞争资源而造成的阻塞问题,若无外力作用,他们将无法推进下去,此时系统处于死锁状态。
在这里插入图片描述

死锁产生的原因

  • 因竞争资源产生死锁
  • 进程顺序推进不当发生死锁
    (数据库层面上也会有死锁发生)

死锁产生的必要条件:

  • 互斥条件:资源每次只能是一个线程使用
  • 请求与保持条件:一个线程因请求资源而阻塞时,对已获取的资源保持不放
  • 不可剥夺条件:线程已获取的资源在未使用之前不能强行剥夺
  • 循环等待条件:若干个线程之间形成一种头尾相连接的循环等待资源关系
    在这里插入图片描述

死锁的预防或解除

预防(事前):破坏产生死锁的四个必要条件

  • 破坏请求与保持条件:资源一次性分配
  • 破坏不可剥夺条件:在线程未满足条件时,释放掉已占有的资源
  • 资源有序分配:系统给每类资源赋予一个编号,每个线程按编号递增的顺序请求资源, 释放则相反

避免(事中):银行家算法
允许线程动态申请资源,系统在资源的分配之前先计算资源分配的安全性,若此次分配不会导致系统进入不安全的状态,则给线程分配该资源,否则进行等待。

检测和恢复(事后)
当线程发现进入死锁了,立即从死锁状态接触掉,采用方式
剥夺资源:从其它线程剥夺足够多的资源给死锁线程,以解除死锁

死锁的案例

  • 生产者消费者使用不当会产生死锁(wait、notify、notifyAll)
  • 多线程获取多把锁,先加锁后释放,后加锁先释放
  • 哲学家就餐问题

实际定位死锁位置的思路

1.首先需要确定java进程是否发生死锁
2.打开jvisualvm工具,专门分析JVMCPU,内存使用情况,以及线程的运行信息查看当前java进程各个线程运行的状态(颜色)
3.通过jvisualvm的线程dump或者jstack命令,把当前java进程所有线程的调用堆栈信息打印出来
4.分析main线程和子线程有没有关键短语:

  • waiting for(资源地址)
  • waiting to lock(资源地址)

5.看线程函数调用栈,定位到源码上,具体问题具体分析

猜你喜欢

转载自blog.csdn.net/Alyson_jm/article/details/89599806