死锁实现和怎样分析死锁

来源:互联网 发布:sql语句查询时的别名 编辑:程序博客网 时间:2024/06/04 08:33

总结:

  1. 最简单的死锁是:线程A持有锁1申请锁2,同时线程B持有锁2申请锁1。-------如果两个线程申请顺序一致,释放顺序同申请顺序也一致,是不会死锁的。
  2. 使用visualvm查看死锁:
    1. 首先会提示发现死锁,然后点击“线程dump”
    2. 查看blocked或者wait的线程,其中Locked ownable synchronizers:表示当前线程持有的锁资源,parking to wait for  表示阻塞等待的锁资源。将多个wait或者blocked的线程,参照死锁特征比较,例如“最简单的死锁”比较。


以下转载自:http://blog.csdn.net/paincupid/article/details/47441187

Java Deadlock Example and How to analyze deadlock situation


所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件。
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
在系统中已经出现死锁后,应该及时检测到死锁的发生,并采取适当的措施来解除死锁。目前处理死锁的方法可归结为以下四种:

1) 预防死锁
  这是一种较简单和直观的事先预防的方法。方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

2) 避免死锁
  该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。

3)检测死锁
  这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源,然后采取适当措施,从系统中将已发生的死锁清除掉。

4)解除死锁
  这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。


悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁不能解决脏读的问题


悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。


Deadlock is a programming situation where two or more threads are blocked forever, this situation arises with at least two threads and two or more resources.

例子:

[java] view plain copy
  1. package com.journaldev.threads;  
  2.    
  3. public class ThreadDeadlock {  
  4.    
  5.     public static void main(String[] args) throws InterruptedException {  
  6.         Object obj1 = new Object();  
  7.         Object obj2 = new Object();  
  8.         Object obj3 = new Object();  
  9.        
  10.         Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");  
  11.         Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");  
  12.         Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");  
  13.            
  14.         t1.start();  
  15.         Thread.sleep(5000);  
  16.         t2.start();  
  17.         Thread.sleep(5000);  
  18.         t3.start();  
  19.            
  20.     }  
  21.    
  22. }  
  23.    
  24. class SyncThread implements Runnable{  
  25.     private Object obj1;  
  26.     private Object obj2;  
  27.    
  28.     public SyncThread(Object o1, Object o2){  
  29.         this.obj1=o1;  
  30.         this.obj2=o2;  
  31.     }  
  32.     @Override  
  33.     public void run() {  
  34.         String name = Thread.currentThread().getName();  
  35.         System.out.println(name + " acquiring lock on "+obj1);  
  36.         synchronized (obj1) {  
  37.          System.out.println(name + " acquired lock on "+obj1);  
  38.          work();  
  39.          System.out.println(name + " acquiring lock on "+obj2);  
  40.          synchronized (obj2) {  
  41.             System.out.println(name + " acquired lock on "+obj2);  
  42.             work();  
  43.         }  
  44.          System.out.println(name + " released lock on "+obj2);  
  45.         }  
  46.         System.out.println(name + " released lock on "+obj1);  
  47.         System.out.println(name + " finished execution.");  
  48.     }  
  49.     private void work() {  
  50.         try {  
  51.             Thread.sleep(30000);  
  52.         } catch (InterruptedException e) {  
  53.             e.printStackTrace();  
  54.         }  
  55.     }  
  56. }  

结果:

[java] view plain copy
  1. t1 acquiring lock on java.lang.Object@6d9dd520  
  2. t1 acquired lock on java.lang.Object@6d9dd520  
  3. t2 acquiring lock on java.lang.Object@22aed3a5  
  4. t2 acquired lock on java.lang.Object@22aed3a5  
  5. t3 acquiring lock on java.lang.Object@218c2661  
  6. t3 acquired lock on java.lang.Object@218c2661  
  7. t1 acquiring lock on java.lang.Object@22aed3a5  
  8. t2 acquiring lock on java.lang.Object@218c2661  
  9. t3 acquiring lock on java.lang.Object@6d9dd520  


Analyze Deadlock 分析死锁

To analyze a deadlock, we need to look at the java thread dump of the application, in last post I explained how we can generate thread dump using VisualVM profiler or using jstack utility.

【为了分析死锁,我们需要用到"visualvm profile"应用,如果想看怎么使用它,请先点链接下载:visualvm-1.3.8 ,然后点上面的链接看使用,这方面在国内介绍也比较比,可以自己百度.】

注:VisualVM 是一款免费的\集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。

以下是用"Java thread dump"分析的结果:

[java] view plain copy
  1. 2012-12-27 19:08:34  
  2. Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):  
  3.    
  4. "Attach Listener" daemon prio=5 tid=0x00007fb0a2814000 nid=0x4007 waiting on condition [0x0000000000000000]  
  5.    java.lang.Thread.State: RUNNABLE  
  6.    
  7. "DestroyJavaVM" prio=5 tid=0x00007fb0a2801000 nid=0x1703 waiting on condition [0x0000000000000000]  
  8.    java.lang.Thread.State: RUNNABLE  
  9.    
  10. "t3" prio=5 tid=0x00007fb0a204b000 nid=0x4d07 waiting for monitor entry [0x000000015d971000]  
  11.    java.lang.Thread.State: BLOCKED (on object monitor)  
  12.     at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)  
  13.     - waiting to lock <0x000000013df2f658> (a java.lang.Object)  
  14.     - locked <0x000000013df2f678> (a java.lang.Object)  
  15.     at java.lang.Thread.run(Thread.java:722)  
  16.    
  17. "t2" prio=5 tid=0x00007fb0a1073000 nid=0x4207 waiting for monitor entry [0x000000015d209000]  
  18.    java.lang.Thread.State: BLOCKED (on object monitor)  
  19.     at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)  
  20.     - waiting to lock <0x000000013df2f678> (a java.lang.Object)  
  21.     - locked <0x000000013df2f668> (a java.lang.Object)  
  22.     at java.lang.Thread.run(Thread.java:722)  
  23.    
  24. "t1" prio=5 tid=0x00007fb0a1072000 nid=0x5503 waiting for monitor entry [0x000000015d86e000]  
  25.    java.lang.Thread.State: BLOCKED (on object monitor)  
  26.     at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)  
  27.     - waiting to lock <0x000000013df2f668> (a java.lang.Object)  
  28.     - locked <0x000000013df2f658> (a java.lang.Object)  
  29.     at java.lang.Thread.run(Thread.java:722)  
  30.    
  31. "Service Thread" daemon prio=5 tid=0x00007fb0a1038000 nid=0x5303 runnable [0x0000000000000000]  
  32.    java.lang.Thread.State: RUNNABLE  
  33.    
  34. "C2 CompilerThread1" daemon prio=5 tid=0x00007fb0a1037000 nid=0x5203 waiting on condition [0x0000000000000000]  
  35.    java.lang.Thread.State: RUNNABLE  
  36.    
  37. "C2 CompilerThread0" daemon prio=5 tid=0x00007fb0a1016000 nid=0x5103 waiting on condition [0x0000000000000000]  
  38.    java.lang.Thread.State: RUNNABLE  
  39.    
  40. "Signal Dispatcher" daemon prio=5 tid=0x00007fb0a4003000 nid=0x5003 runnable [0x0000000000000000]  
  41.    java.lang.Thread.State: RUNNABLE  
  42.    
  43. "Finalizer" daemon prio=5 tid=0x00007fb0a4800000 nid=0x3f03 in Object.wait() [0x000000015d0c0000]  
  44.    java.lang.Thread.State: WAITING (on object monitor)  
  45.     at java.lang.Object.wait(Native Method)  
  46.     - waiting on <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)  
  47.     at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)  
  48.     - locked <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)  
  49.     at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)  
  50.     at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)  
  51.    
  52. "Reference Handler" daemon prio=5 tid=0x00007fb0a4002000 nid=0x3e03 in Object.wait() [0x000000015cfbd000]  
  53.    java.lang.Thread.State: WAITING (on object monitor)  
  54.     at java.lang.Object.wait(Native Method)  
  55.     - waiting on <0x000000013de75320> (a java.lang.ref.Reference$Lock)  
  56.     at java.lang.Object.wait(Object.java:503)  
  57.     at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)  
  58.     - locked <0x000000013de75320> (a java.lang.ref.Reference$Lock)  
  59.    
  60. "VM Thread" prio=5 tid=0x00007fb0a2049800 nid=0x3d03 runnable   
  61.    
  62. "GC task thread#0 (ParallelGC)" prio=5 tid=0x00007fb0a300d800 nid=0x3503 runnable   
  63.    
  64. "GC task thread#1 (ParallelGC)" prio=5 tid=0x00007fb0a2001800 nid=0x3603 runnable   
  65.    
  66. "GC task thread#2 (ParallelGC)" prio=5 tid=0x00007fb0a2003800 nid=0x3703 runnable   
  67.    
  68. "GC task thread#3 (ParallelGC)" prio=5 tid=0x00007fb0a2004000 nid=0x3803 runnable   
  69.    
  70. "GC task thread#4 (ParallelGC)" prio=5 tid=0x00007fb0a2005000 nid=0x3903 runnable   
  71.    
  72. "GC task thread#5 (ParallelGC)" prio=5 tid=0x00007fb0a2005800 nid=0x3a03 runnable   
  73.    
  74. "GC task thread#6 (ParallelGC)" prio=5 tid=0x00007fb0a2006000 nid=0x3b03 runnable   
  75.    
  76. "GC task thread#7 (ParallelGC)" prio=5 tid=0x00007fb0a2006800 nid=0x3c03 runnable   
  77.    
  78. "VM Periodic Task Thread" prio=5 tid=0x00007fb0a1015000 nid=0x5403 waiting on condition   
  79.    
  80. JNI global references: 114  
  81.    
  82.    
  83. Found one Java-level deadlock:  
  84. =============================  
  85. "t3":  
  86.   waiting to lock monitor 0x00007fb0a1074b08 (object 0x000000013df2f658, a java.lang.Object),  
  87.   which is held by "t1"  
  88. "t1":  
  89.   waiting to lock monitor 0x00007fb0a1010f08 (object 0x000000013df2f668, a java.lang.Object),  
  90.   which is held by "t2"  
  91. "t2":  
  92.   waiting to lock monitor 0x00007fb0a1012360 (object 0x000000013df2f678, a java.lang.Object),  
  93.   which is held by "t3"  
  94.    
  95. Java stack information for the threads listed above:  
  96. ===================================================  
  97. "t3":  
  98.     at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)  
  99.     - waiting to lock <0x000000013df2f658> (a java.lang.Object)  
  100.     - locked <0x000000013df2f678> (a java.lang.Object)  
  101.     at java.lang.Thread.run(Thread.java:722)  
  102. "t1":  
  103.     at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)  
  104.     - waiting to lock <0x000000013df2f668> (a java.lang.Object)  
  105.     - locked <0x000000013df2f658> (a java.lang.Object)  
  106.     at java.lang.Thread.run(Thread.java:722)  
  107. "t2":  
  108.     at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)  
  109.     - waiting to lock <0x000000013df2f678> (a java.lang.Object)  
  110.     - locked <0x000000013df2f668> (a java.lang.Object)  
  111.     at java.lang.Thread.run(Thread.java:722)  
  112.    
  113. Found 1 deadlock.  

The thread dump output clearly shows the deadlock situation and threads and resources involved causing deadlock situation.

For analyzing deadlock, we need to look out for the threads with state as BLOCKED and then the resources it’s waiting to lock, every resource has a unique ID using which we can find which thread is already holding the lock on the object. For example Thread “t3″ is waiting to lock 0x000000013df2f658 but it’s already locked by thread “t1″.

Once we analyze the deadlock situation and found out the threads which are causing deadlock, we need to make code changes to avoid deadlock situation.

Avoid deadlock 避免死锁

These are some of the guidelines using which we can avoid most of the deadlock situations.

  • Avoid Nested Locks: This is the most common reason for deadlocks, avoid locking another resource if you already hold one. It’s almost impossible to get deadlock situation if you are working with only one object lock. For example, here is the another implementation of run() method without nested lock and program runs successfully without deadlock situation.
  • 【粗译: 避免嵌套死锁:最是引起死锁最常见的原因,如果你已经有锁了避免锁住另一个资源。如果你只工作在一个对象上的锁,这是最不可能产生死锁的了。例如,这里有一个run方法的实现,在方法中,没有嵌套锁,程序会正常的运行而且不会产生死锁。

[java] view plain copy
  1. public void run() {  
  2.     String name = Thread.currentThread().getName();  
  3.     System.out.println(name + " acquiring lock on " + obj1);  
  4.     synchronized (obj1) {  
  5.         System.out.println(name + " acquired lock on " + obj1);  
  6.         work();  
  7.     }  
  8.     System.out.println(name + " released lock on " + obj1);  
  9.     System.out.println(name + " acquiring lock on " + obj2);  
  10.     synchronized (obj2) {  
  11.         System.out.println(name + " acquired lock on " + obj2);  
  12.         work();  
  13.     }  
  14.     System.out.println(name + " released lock on " + obj2);  
  15.    
  16.     System.out.println(name + " finished execution.");  
  17. }  

  • Lock Only What is Required: You should acquire lock only on the resources you have to work on, for example in above program I am locking the complete Object resource but if we are only interested in one of it’s fields, then we should lock only that specific field not complete object. 【粗译:只对需要的加锁: 你应该在为,在工作中的唯一资源(可能是一个局部,也可能是个对象,也可可能范围更广,但是那只是用到的资源;对于不需要的部分,不应该加锁)上的去获得锁,例如上面的程序,我只在完成的对象资源上加锁,但是如果我们只对某些部分感兴趣,那么我们应该只对那部分加锁,而不是整个对象。
  • Avoid waiting indefinitely: You can get deadlock if two threads are waiting for each other to finish indefinitely using thread join. If your thread has to wait for another thread to finish, it’s always best to use join with maximum time you want to wait for thread to finish.【避免无限期地等待:如果2个线程方法相互等待使用资源,那么很容易产生死锁。如果一个线程等待另一个线程完成,我们最好使用join()来等待另一个线程完成任务。

If you liked this tutorial, make sure to check out other java thread tutorial.


参考: http://www.journaldev.com/1058/java-deadlock-example-and-how-to-analyze-deadlock-situation


转载请注明:http://blog.csdn.net/paincupid/article/details/47441187


0 0