Java死锁_动力节点Java学院整理

 更新时间:2017年06月02日 14:56:02   投稿:mrr  
死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它

死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它。

Java死锁范例

ThreadDeadlock.java

package com.bjpowernode.threads;
public class ThreadDeadlock {
  public static void main(String[] args) throws InterruptedException {
    Object obj1 = new Object();
    Object obj2 = new Object();
    Object obj3 = new Object();
    Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
    Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
    Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
    t1.start();
    Thread.sleep(5000);
    t2.start();
    Thread.sleep(5000);
    t3.start();
  }
}
class SyncThread implements Runnable{
  private Object obj1;
  private Object obj2;
  public SyncThread(Object o1, Object o2){
    this.obj1=o1;
    this.obj2=o2;
  }
  @Override
  public void run() {
    String name = Thread.currentThread().getName();
    System.out.println(name + " acquiring lock on "+obj1);
    synchronized (obj1) {
     System.out.println(name + " acquired lock on "+obj1);
     work();
     System.out.println(name + " acquiring lock on "+obj2);
     synchronized (obj2) {
      System.out.println(name + " acquired lock on "+obj2);
      work();
    }
     System.out.println(name + " released lock on "+obj2);
    }
    System.out.println(name + " released lock on "+obj1);
    System.out.println(name + " finished execution.");
  }
  private void work() {
    try {
      Thread.sleep(30000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

在上面的程序中同步线程正完成Runnable的接口,它工作的是两个对象,这两个对象向对方寻求死锁而且都在使用同步阻塞。

在主函数中,我使用了三个为同步线程运行的线程,而且在其中每个线程中都有一个可共享的资源。

这些线程以向第一个对象获取封锁这种方式运行。但是当它试着像第二个对象获取封锁时,它就会进入等待状态,因为它已经被另一个线程封锁住了。这样,在线程引起死锁的过程中,就形成了一个依赖于资源的循环。

当我执行上面的程序时,就产生了输出,但是程序却因为死锁无法停止。

 t1 acquiring lock on java.lang.Object@6d9dd520
t1 acquired lock on java.lang.Object@6d9dd520
t2 acquiring lock on java.lang.Object@22aed3a5
t2 acquired lock on java.lang.Object@22aed3a5
t3 acquiring lock on java.lang.Object@218c2661
t3 acquired lock on java.lang.Object@218c2661
t1 acquiring lock on java.lang.Object@22aed3a5
t2 acquiring lock on java.lang.Object@218c2661
t3 acquiring lock on java.lang.Object@6d9dd520

在此我们可以清楚地在输出结果中辨认出死锁局面,但是在我们实际生活所用的应用中,发现死锁并将它排除是非常难的。

分析死锁

 2012-12-27 19:08:34
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):
 "Attach Listener" daemon prio=5 tid=0x00007fb0a2814000 nid=0x4007 waiting on condition [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE
"DestroyJavaVM" prio=5 tid=0x00007fb0a2801000 nid=0x1703 waiting on condition [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE
"t3" prio=5 tid=0x00007fb0a204b000 nid=0x4d07 waiting for monitor entry [0x000000015d971000]
  java.lang.Thread.State: BLOCKED (on object monitor)
  at com.bjpowernode.threads.SyncThread.run(ThreadDeadlock.java:41)
  - waiting to lock <0x000000013df2f658> (a java.lang.Object)
  - locked <0x000000013df2f678> (a java.lang.Object)
  at java.lang.Thread.run(Thread.java:722)
"t2" prio=5 tid=0x00007fb0a1073000 nid=0x4207 waiting for monitor entry [0x000000015d209000]
  java.lang.Thread.State: BLOCKED (on object monitor)
  at com.bjpowernode.threads.SyncThread.run(ThreadDeadlock.java:41)
  - waiting to lock <0x000000013df2f678> (a java.lang.Object)
  - locked <0x000000013df2f668> (a java.lang.Object)
  at java.lang.Thread.run(Thread.java:722)
"t1" prio=5 tid=0x00007fb0a1072000 nid=0x5503 waiting for monitor entry [0x000000015d86e000]
  java.lang.Thread.State: BLOCKED (on object monitor)
  at com.bjpowernode.threads.SyncThread.run(ThreadDeadlock.java:41)
  - waiting to lock <0x000000013df2f668> (a java.lang.Object)
  - locked <0x000000013df2f658> (a java.lang.Object)
  at java.lang.Thread.run(Thread.java:722)
"Service Thread" daemon prio=5 tid=0x00007fb0a1038000 nid=0x5303 runnable [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=5 tid=0x00007fb0a1037000 nid=0x5203 waiting on condition [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=5 tid=0x00007fb0a1016000 nid=0x5103 waiting on condition [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=5 tid=0x00007fb0a4003000 nid=0x5003 runnable [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=5 tid=0x00007fb0a4800000 nid=0x3f03 in Object.wait() [0x000000015d0c0000]
  java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
  - locked <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
  at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
"Reference Handler" daemon prio=5 tid=0x00007fb0a4002000 nid=0x3e03 in Object.wait() [0x000000015cfbd000]
  java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x000000013de75320> (a java.lang.ref.Reference$Lock)
  at java.lang.Object.wait(Object.java:503)
  at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
  - locked <0x000000013de75320> (a java.lang.ref.Reference$Lock)
"VM Thread" prio=5 tid=0x00007fb0a2049800 nid=0x3d03 runnable 
"GC task thread#0 (ParallelGC)" prio=5 tid=0x00007fb0a300d800 nid=0x3503 runnable 
"GC task thread#1 (ParallelGC)" prio=5 tid=0x00007fb0a2001800 nid=0x3603 runnable 
"GC task thread#2 (ParallelGC)" prio=5 tid=0x00007fb0a2003800 nid=0x3703 runnable 
"GC task thread#3 (ParallelGC)" prio=5 tid=0x00007fb0a2004000 nid=0x3803 runnable 
"GC task thread#4 (ParallelGC)" prio=5 tid=0x00007fb0a2005000 nid=0x3903 runnable 
"GC task thread#5 (ParallelGC)" prio=5 tid=0x00007fb0a2005800 nid=0x3a03 runnable 
"GC task thread#6 (ParallelGC)" prio=5 tid=0x00007fb0a2006000 nid=0x3b03 runnable 
"GC task thread#7 (ParallelGC)" prio=5 tid=0x00007fb0a2006800 nid=0x3c03 runnable 
"VM Periodic Task Thread" prio=5 tid=0x00007fb0a1015000 nid=0x5403 waiting on condition 
JNI global references: 114
Found one Java-level deadlock:
=============================
"t3":
 waiting to lock monitor 0x00007fb0a1074b08 (object 0x000000013df2f658, a java.lang.Object),
 which is held by "t1"
"t1":
 waiting to lock monitor 0x00007fb0a1010f08 (object 0x000000013df2f668, a java.lang.Object),
 which is held by "t2"
"t2":
 waiting to lock monitor 0x00007fb0a1012360 (object 0x000000013df2f678, a java.lang.Object),
 which is held by "t3"
Java stack information for the threads listed above:
===================================================
"t3":
  at com.bjpowernode.threads.SyncThread.run(ThreadDeadlock.java:41)
  - waiting to lock <0x000000013df2f658> (a java.lang.Object)
  - locked <0x000000013df2f678> (a java.lang.Object)
  at java.lang.Thread.run(Thread.java:722)
"t1":
  at com.bjpowernode.threads.SyncThread.run(ThreadDeadlock.java:41)
  - waiting to lock <0x000000013df2f668> (a java.lang.Object)
  - locked <0x000000013df2f658> (a java.lang.Object)
  at java.lang.Thread.run(Thread.java:722)
"t2":
  at com.bjpowernode.threads.SyncThread.run(ThreadDeadlock.java:41)
  - waiting to lock <0x000000013df2f678> (a java.lang.Object)
  - locked <0x000000013df2f668> (a java.lang.Object)
  at java.lang.Thread.run(Thread.java:722)
Found 1 deadlock.

这三个线程转存的输出清楚地说明了死锁环境和线程,以及包含死锁环境的资源。

为了分析死锁,我们需要关注死锁状态的线程,然后资源再等待去封锁,每一个资源都有一个独特的ID,有了这个ID我们就能发现是哪一个进程已经封锁住对象。举个例子,线程“t3”正在等待封锁0x000000013df2f658,但是它已经被线程“t1”封锁住了。

当我们分析死锁环境的时候,如果发现线程正在引起死锁,这是我们就要改变代码来避免死锁的产生。

避免死锁

有很多方针可供我们使用来避免死锁的局面。

避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。例如,这里是另一个运行中没有嵌套封锁的run()方法,而且程序运行没有死锁局面,运行得很成功。

public void run() {
  String name = Thread.currentThread().getName();
  System.out.println(name + " acquiring lock on " + obj1);
  synchronized (obj1) {
    System.out.println(name + " acquired lock on " + obj1);
    work();
  }
  System.out.println(name + " released lock on " + obj1);
  System.out.println(name + " acquiring lock on " + obj2);
  synchronized (obj2) {
    System.out.println(name + " acquired lock on " + obj2);
    work();
  }
  System.out.println(name + " released lock on " + obj2);
 
  System.out.println(name + " finished execution.");
}

只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。

避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。

相关文章

  • guava中Multimap、HashMultimap用法小结

    guava中Multimap、HashMultimap用法小结

    这篇文章主要介绍了guava中Multimap、HashMultimap使用,Multimap它可以很简单的实现一些功能,LinkedHashMultimap实现类与HashMultimap类的实现方法一样,唯一的区别是LinkedHashMultimap保存了记录的插入顺序,本文就这些内容讲解的非常详细,需要的朋友参考下吧
    2022-05-05
  • Spring实现文件上传功能

    Spring实现文件上传功能

    本篇文章主要介绍了Spring实现文件上传功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Java 的抽象类原理与用法分析

    Java 的抽象类原理与用法分析

    这篇文章主要介绍了Java 的抽象类原理与用法,结合实例形式分析了java抽象类与接口的相关概念、原理、使用方法及操作注意事项,需要的朋友可以参考下
    2019-12-12
  • java根据不同的参数调用不同的实现类操作

    java根据不同的参数调用不同的实现类操作

    这篇文章主要介绍了java根据不同的参数调用不同的实现类操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Spring AOP简介及统一处理

    Spring AOP简介及统一处理

    AOP面向切面编程,它是一种思想,它是对某一类事情的集中处理,本文给大家介绍Spring AOP简介及统一处理,感兴趣的朋友跟随小编一起看看吧
    2023-09-09
  • Java中LinkedHashSet的实现原理详解

    Java中LinkedHashSet的实现原理详解

    这篇文章主要介绍了Java中LinkedHasSet的实现原理详解,LinkedHashSet 是具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现,此实现与HashSet 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表,需要的朋友可以参考下
    2023-09-09
  • Java容器ArrayList知识点总结

    Java容器ArrayList知识点总结

    本篇文章给大家分享了Java容器ArrayList的相关知识点,对此有需要的朋友可以跟着学习参考下。
    2018-05-05
  • Mybatis-plus多租户项目实战进阶指南

    Mybatis-plus多租户项目实战进阶指南

    多租户是一种软件架构技术,在多用户的环境下共有同一套系统,并且要注意数据之间的隔离性,下面这篇文章主要给大家介绍了关于Mybatis-plus多租户项目实战进阶的相关资料,需要的朋友可以参考下
    2022-02-02
  • springboot aop配合反射统一签名验证实践

    springboot aop配合反射统一签名验证实践

    这篇文章主要介绍了springboot aop配合反射统一签名验证实践,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • java打印表格 将ResultSet中的数据打印成表格问题

    java打印表格 将ResultSet中的数据打印成表格问题

    这篇文章主要介绍了java打印表格 将ResultSet中的数据打印成表格问题。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12

最新评论