JVM可以检测到synchronized导致的死锁,考虑下面的代码:
public class ClassA { public static String monitor1 = "monitor1"; public static String monitor2 = "monitor2"; public static void main(String[] args) { Thread thread1 = new Thread(new Runnable() { public void run() { try { synchronized (monitor1) { System.out.println(Thread.currentThread().getName() + ": got monitor1"); Thread.sleep(5000); synchronized (monitor2) { System.out.println(Thread.currentThread().getName() + ": got monitor2"); } } } catch (InterruptedException e) {} } }, "I‘m Thread1"); thread1.start(); Thread thread2 = new Thread(new Runnable() { public void run() { try { synchronized (monitor2) { System.out.println(Thread.currentThread().getName() + ": got monitor2"); Thread.sleep(5000); synchronized (monitor1) { System.out.println(Thread.currentThread().getName() + ": got monitor1"); } } } catch (InterruptedException e) {} } }, "I‘m Thread2"); thread2.start(); } }
代码中有意制造了典型的死锁情况,即在持有资源的情况下请求新的资源,并且两个线程交叉请求资源,从而导致在特定情况下发生死锁。
在JVM监测中可以明显看到死锁并可以准确定位造成死锁的代码,如下图:
继续进行Thread Dump,在Thread Dump中发现错误代码的位置,如下图:
其中明确说明了造成死锁的原因。
上面描述的死锁是有意制造的简单场景,实际系统中的情况通常复杂得多,因此在开发过程中synchronized的使用应该谨慎,因为死锁很容易监测出来,但无法在JVM运行过程中简单地处理死锁。
Java开发过程中,无论是使用synchronized关键字,还是使用其他锁定机制(如java.util.concurrent.locks.*)中的方法,在编程错误的情况下都可能出现死锁。死锁是操作系统课程中的重要内容,在多线程环境中编程的程序员应该了解其概念及如何避免死锁。
附:死锁产生的必要条件:
如果在系统中同时具备下面四个必要条件时,那么可能发生死锁。换句话说,只要下面四个条件有一个不具备,系统就不会出现死锁。
上面四个条件在死锁时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。
原文:http://www.cnblogs.com/xiongmaotailang/p/5249712.html