博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java死锁定位与预防
阅读量:2431 次
发布时间:2019-05-10

本文共 2009 字,大约阅读时间需要 6 分钟。

死锁

死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。

死锁发生的原因

死锁的发生是由于资源竞争导致的,导致死锁的原因如下:

  • 系统资源不足,如果系统资源充足,死锁出现的可能性就很低。
  • 进程(线程)运行推进的顺序不合适。
  • 资源分配不当等。
死锁发生的条件

死锁的发生的四个必要条件:

  • 互斥条件:一个资源每次只能被一个进程使用。
  • 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不可强行占有:进程(线程)已获得的资源,在未使用完之前,不能强行剥夺。
  • 循环等待条件:若干进程(线程)之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

死锁的例子

为了说明死锁,我们下面举一个例子来说明:

这里写图片描述

线程A持有资源A然后试图获取资源B,线程2持有资源B同时试图获取资源A,这样线程A和B都不能获取彼此想要的资源,导致整个程序不能向下推进。具体代码如下:

class DeadLockRunnable implements Runnable {
private String first; private String second; public DeadLockRunnable(String first, String second) {
this.first = first; this.second = second; } @Override public void run() {
synchronized (first) {
System.out.println(Thread.currentThread().getName() + " obtain: " + first); try {
Thread.sleep(100); synchronized (second) {
System.out.println(Thread.currentThread().getName() + " obtain: " + second); } } catch (InterruptedException e) {
e.printStackTrace(); } } }}public class DeadLock {
public static void main(String[] args) throws InterruptedException {
String lockA = "lockA"; String lockB = "LockB"; Thread t1 = new Thread(new DeadLockRunnable(lockA, lockB)); Thread t2 = new Thread(new DeadLockRunnable(lockB, lockA)); t1.start(); t2.start(); t1.join(); t2.join(); }}

运行结果:

这里写图片描述

从结果中可以看出,两个线程都不能再次获得想要的资源,程序一直处于“停滞”状态。

死锁的定位与预防

那么出现这种情况怎么定位呢?

  • 通过jdk提供的命令
    我们可以使用jstack或者类似Jconsole等图形化工具,查看线程的状态。上面程序jstack输出如下:
    这里写图片描述

通过输出我们看到Thread-1和Thread-0都处于BLOCKED状态。至此我们基本可以知道程序发生了死锁。

  • 分析CPU占用情况
    根据死锁的定义,我们可以得出死锁一定会导致有线程处于”饥饿“状态而一直占用CPU时间片。因此可以通过排查出使用CPU时间片最高的线程,再打出该线程的堆栈信息,最后排查代码找出死锁的原因。

死锁的预防

  • 尽量避免使用多个锁,并且只有需要时才持有锁。
  • 如果使用多个锁,一定要设计好锁的获取顺序。
  • 使用带有超时的方法,为程序带来更多的可控性,比如指定获取锁的时间最多为5秒,超时就放弃。
  • 通过一些代码静态检查工具发现可能存在的死锁问题,比如FindBugs。
你可能感兴趣的文章
【c语言】写一个函数返回参数二进制中 1 的个数 比如: 15 0000 1111 4 个 1
查看>>
【C语言】【编程练习】字符大小写问题
查看>>
【C语言】【编程练习】判断100到200之间的素数
查看>>
【C语言】将数组A中的内容和数组B中的内容进行交换。(数组一样大)
查看>>
【C语言】实现一个简单小游戏-三子棋
查看>>
【C语言】c语言程序编译运行过程;静态链接,动态链接;
查看>>
【C语言】数据在计算机中的存储与运算
查看>>
【计算机】什么是计算机中的大端小端
查看>>
【C语言】深入理解const,volatile,static关键字
查看>>
【C语言】c/c++程序的内存是如何分配的?
查看>>
【C语言】深入理解C语言的函数调用过程
查看>>
【C语言】C语言中格式化字符的具体用法(C语言中%的那些事)
查看>>
【java】十大经典排序算法(动图演示)
查看>>
【代码规范】google开源c\c++项目代码规范
查看>>
【C语言】c语言常用的几个函数源代码【strlen,strcpy,strcat,strstr】
查看>>
【C语言】杨辉三角问题
查看>>
【C语言】size与strlen的区别解析
查看>>
【C语言】指针深入理解-指针与数组的关系
查看>>
【C语言】C语言中常用函数源代码【strncpy ,strncat ,strncmp】
查看>>
【linux】入门学习Linux常用必会命令实例详解
查看>>