【Java多线程】之七:死锁例子
2015-08-09 12:03
489 查看
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. Here I have written a simple program that will cause deadlock scenario and then we will see how to analyze it
Java Deadlock Example
ThreadDeadlock.java
In above program SyncThread is implementing Runnable interface and it works on two Objects by acquiring lock on each one of them one by one using synchronized block.
In main method, I have three threads running for SyncThread and there is a shared resource between each of the threads. The threads are run in such a way that it will be able to acquire lock on the first object but when it’s trying to acquire lock on second object, it goes on wait state because it’s already locked by another thread. This forms a cyclic dependency for resource between Threads causing deadlock.
When I execute the above program, here is the output generated but program never terminates because of deadlock.
Here we can clearly identify the deadlock situation from the output but in real life applications it’s very hard to find the deadlock situation and debug them.
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.
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.
Java Deadlock Example
ThreadDeadlock.java
package com.journaldev.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(); } } }
In above program SyncThread is implementing Runnable interface and it works on two Objects by acquiring lock on each one of them one by one using synchronized block.
In main method, I have three threads running for SyncThread and there is a shared resource between each of the threads. The threads are run in such a way that it will be able to acquire lock on the first object but when it’s trying to acquire lock on second object, it goes on wait state because it’s already locked by another thread. This forms a cyclic dependency for resource between Threads causing deadlock.
When I execute the above program, here is the output generated but program never terminates because of deadlock.
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
Here we can clearly identify the deadlock situation from the output but in real life applications it’s very hard to find the deadlock situation and debug them.
Avoid deadlock
These are some of the guidelines using which we can avoid most of the deadlock situations.
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."); }
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.
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.
相关文章推荐
- Spring 3整合Quartz 2实现定时任务三:动态暂停 恢复 修改和删除任务
- java中的UDP总结
- Spring定时任务配置
- java并发(四) CopyOnWrite容器
- 谈谈java中成员变量与成员方法继承的问题
- 重学java23种设计模式(15)解释器模式
- java实现字符串逆转
- Java中的参数传递方式
- 单例模式(java 实现 Singleton)(二)
- 【Java设计模式】· 享元模式 (Flyweight Pattern)
- eclipse环境下无法创建android virtual Devices(AVD)问题解决办法汇总
- 求1~100间的素数.java
- Java中abstract class 和 interface 的解释和他们的异同点(转)
- 编写前n项阶乘之和.java
- 编程打印三角形数字图案.java
- Java 代码检查工具
- springMvc 之 【javaBean读取属性配置文件中的值】---非注解方式
- Struts2基本环境搭建过程中容易出现的丢包问题
- Java 并发专题 : Timer的缺陷 用ScheduledExecutorService替代
- Java功底篇系列-01-从==/equals/hashCode开始