一个简单的死锁代码#
public class DeadLock{ static Object o1 = new Object(); static Object o2 = new Object(); public static void main(String[] args) { new Thread(new Runnable() { public void run() { synchronized (o1) { System.out.println("线程1锁o1"); try { Thread.sleep(1000);//让当前线程睡眠,保证让另一线程得到o2,防止这个线程启动一下连续获得o1和o2两个对象的锁。 synchronized (o2) { System.out.println("线程1锁o2"); } } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); new Thread(new Runnable() { public void run() { synchronized (o2) { System.out.println("线程2锁o2"); synchronized (o1) { System.out.println("线程2锁o1"); } } } }).start(); } }
什么是死锁
死锁,是指多个线程在运行过程中因争夺资源而造成的一种僵局,若无外力作用,它们都将无法再向前推进。
死锁的4个必要条件
互斥条件:一个资源每次只能被一个线程使用;
请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放;
不剥夺条件:进程已经获得的资源,在未使用完之前,不能强行剥夺;
循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。
如何避免(预防)死锁
破坏“请求和保持”条件:让进程在申请资源时,一次性申请所有需要用到的资源,不要一次一次来申请,当申请的资源有一些没空,那就让线程等待。不过这个方法比较浪费资源,进程可能经常处于饥饿状态。还有一种方法是,要求进程在申请资源前,要释放自己拥有的资源。
破坏“不可抢占”条件:允许进程进行抢占,方法一:如果去抢资源,被拒绝,就释放自己的资源。方法二:操作系统允许抢,只要你优先级大,可以抢到。
破坏“循环等待”条件:将系统中的所有资源统一编号,进程可在任何时刻提出资源申请,但所有申请必须按照资源的编号顺序提出(指定获取锁的顺序,顺序加锁)。