死锁案例
来源:互联网 发布:虚拟变量数据什么意思 编辑:程序博客网 时间:2024/06/01 07:25
JAVA死锁与解决
死锁如何解决
假设有两个线程,分别代表两个饥饿的人,他们必须共享刀叉并轮流吃饭。他们都需要获得两个锁:共享刀和共享叉的锁。
假如线程 “A”获得了刀,而线程“B”获得了叉。线程“A”就会进入阻塞状态来等待获得叉,而线程“B”则阻塞来等待“A”所拥有的刀。这样就造成了死锁。
避免死锁的一个通用的经验法则是:
当几个线程都要访问共享资源A、B、C时,保证使每个线程都按照同样的顺序去访问它们,比如都先访问A,在访问B和C。
即让所有的线程按照同样的顺序获得一组锁。
死锁就是两个或两个以上的线程被无限的阻塞,线程之间相互等待所需资源。这种情况可能发生在当两个线程尝试获取其它资源的锁,而每个线程又陷入无限等待其它资源锁的释放,除非一个用户进程被终止。就 JavaAPI 而言,线程死锁可能发生在一下情况。
- 当两个线程相互调用 Thread.join ()
- 当两个线程使用嵌套的同步块,一个线程占用了另外一个线程必需的锁,互相等待时被阻塞就有可能出现死锁。
下面这道题,是考死锁的,比较简单,想两个问题:
1.什么时候会造成死锁
2.wait和notify释放了哪个锁,因为题目中有两个锁。
import java.util.LinkedList;public class DeadLockTest { LinkedList list = new LinkedList(); public synchronized void push(Object x) { System.out.println("push"); synchronized (list) { list.addLast(x); notify(); } } public synchronized Object pop() throws Exception { synchronized (list) { if (list.size() <= 0) { wait(); } return list.removeLast(); } } public static void main(String[] args) throws InterruptedException { final DeadLockTest deadLockTest = new DeadLockTest(); Thread thread = new Thread(new Runnable() { public void run() { try { deadLockTest.pop(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); thread.start(); Thread.sleep(2000); Thread threadPush = new Thread(new Runnable() { public void run() { try { deadLockTest.push("push thread"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); threadPush.start(); }}
当List为空时,pop的锁一直wait,需要唤醒,而push也获取不到List的锁,进而无法执行notify唤醒方法,所以死锁。
来源:http://tomyz0223.iteye.com/blog/1050230
Example2:
class DeadLockSample{ public final Object lock1 = new Object(); public final Object lock2 = new Object(); public void methodOne(){ synchronized(lock1){ ... synchronized(lock2){...} } } public void methodTwo(){ synchronized(lock2){ ... synchronized(lock1){...} } } }
假设场景:线程A调用methodOne(),获得lock1的隐式锁后,在获得lock2的隐式锁之前线程B进入运行,调用methodTwo(),抢先获得了lock2的隐式锁,此时线程A等着线程B交出lock2,线程B等着lock1进入方法块,死锁就这样被创造出来了。
Example3:
import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class LockOrdering { private Lock lock1 = new ReentrantLock(); private Lock lock2 = new ReentrantLock(); public void op1() { while(true) { if(lock1.tryLock()) {//先获取lock1 try { System.out.println("do sth in op1 with lock1..."); try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) {} System.out.println("after sleep in op1"); if(lock2.tryLock()) {//再获取lock2 try { System.out.println("do sth in op1 with lock2..."); return;//退出循环 } finally { lock2.unlock(); } } } finally { lock1.unlock(); } } } } public void op2() { //锁获取的顺序与op1相反 while(true) { if(lock2.tryLock()) {//先获取lock2 try { System.out.println("do sth in op2 with lock2..."); try { TimeUnit.SECONDS.sleep(1); } catch (Exception e) {} System.out.println("after sleep in op2"); if(lock1.tryLock()) {//再获取lock1 try { System.out.println("do sth in op2 with lock1..."); return;//退出循环 } finally { lock1.unlock(); } } } finally { lock2.unlock(); } } } } public static void main(String... args) { final LockOrdering test = new LockOrdering(); new Thread() { public void run() { test.op1(); } }.start(); new Thread() { public void run() { test.op2(); } }.start(); }}
这只是个例子,简单的使用了tryLock,而实际上,带超时时间的重载版本的tryLock更实用。如果上述两个操作都同时做,op1获取lock1,op2获取lock2,op1将获取不到lock2,op2也获取不到lock1,然后op1释放lock1,op2释放lock2,接着又重复这样的操作,就可能导致死循环,当然,这只是理论上的一种可能性,实际CPU要做很多事情,并不会出现这类低概率事件。如果使用带超时时间的tryLock,且每次使用的时间都不同,则几乎可避免这类情况。这有点儿类似网络中的碰撞以及解决碰撞的二进制指数退避算法。
例子3来源:内置锁与LOCK
- 死锁案例
- 简单多线程死锁案例
- Thread 产生死锁案例
- java死锁案例
- mysql 死锁案例
- java死锁案例
- 死锁的案例
- Android 死锁解题案例
- 简单死锁案例
- 经典死锁案例-哲学家就餐
- 多线程中死锁的案例
- java中死锁的案例
- 多线程学习之死锁案例
- Android 死锁解题案例 - 【01】
- 死锁案例及查看方法
- 一个多线程死锁案例,如何避免及解决死锁问题?
- MySQL批量更新死锁案例分析
- 案例:死锁引起的应用挂起
- (js)上传图片预览
- genymotion the file is corrupt 无法下载手机虚拟机问题解决办法
- HashSet
- sql server 2000 datetime 默认值设置问题
- wireshark抓取不到本地回路的数据包
- 死锁案例
- java日期操作
- Future接口和FutureTask类【FutureTask实现了Runnable和Future接口】
- as打包内存不足的解决方法
- 还有人开发工作流吗?还有使用JBPM进行开发的吗?
- 使用CompletionService获取多线程返回值
- Java注解annotation用法和自定义注解处理器
- px,em,rem,vh,vw,vmin,vmax的区别及浏览器支持
- javascript 操作select