什么是死锁?
答:两个或多个线程互相持有对方需要的锁而导致这些线程全部处于永久阻塞状态。如:线程A持有对象1的锁,等待对象2的锁;线程B持有对象2的锁,等待对象1的锁。
发生死锁的四个必要条件:
1.互斥条件:对于访问某些公共资源的线程需实现线程同步,即不能同时访问。
2.不剥夺条件:未使用完不可强行剥夺
3.请求和保持条件:进程至少持有一个资源同时要请求新的资源。
4.环路等待条件:存在一个线程-资源环形链。在进程集合{p0,p1...pn}中,p0正在等待p1占用的资源,p1等待p2占用的资源...pn等待p0占用的资源。
死锁的代码实现:
public class DeadLock implements Runnable{ //注意,这里需要定义为static,否则t1和t2两个线程中的o1,o2均为新创建的,也就是此o1非彼o1,o2也一样,即不存在资源冲突,不会发生死锁。字符串除外,因为有字符串池 private static Object o1=new Object(); private static Object o2=new Object(); private int flag; public DeadLock(int flag){ this.flag=flag; } @Override public void run() { if(flag==0){ synchronized (o1){ System.out.println("t1 Get the lock of o1"); try{ Thread.sleep(1000); } catch (InterruptedException ex){ ex.printStackTrace(); } synchronized (o2){ System.out.println("t1 Get the lock of o2"); } } } else{ synchronized (o2){ System.out.println("t2 Get the lock of o2"); try{ Thread.sleep(1000); } catch (InterruptedException ex){ ex.printStackTrace(); } synchronized (o1){ System.out.println("t2 Get the lock of o1"); } } } } public static void main(String[]args){ DeadLock D1=new DeadLock(0); DeadLock D2=new DeadLock(1); Thread t1=new Thread(D1); Thread t2=new Thread(D2); t1.start(); t2.start(); } }
解决死锁的三种方案:
1.资源排序
如上诉代码中将else{}中的o1和o2调换顺序即可。
2.加锁时限
如果一个线程没有在指定的时间期限内获取到锁,则结束当前线程并释放掉已获得的锁。终止线程的方法:stop()会释放掉锁但易导致数据不一致。suspend()终止线程但不会释放掉锁。
3.死锁检测
参考:线程死锁的原理及解决方式