Java线程——线程之间的死锁
一,什么是死锁?
所谓的死锁是指多个线程因为竞争资源而造成的一种僵局(相互等待),若无外力的作用,这些进程都不能向前推进。
二,死锁产生的条件?
(1)互斥条件:线程要求对所分配的资源(如打印机)进行排他性控制,既在某一段时间内,资源只能被一个线程所占有。
(2)不剥夺条件:线程所获得的资源在未使用完前,不能被其他的线程强行夺走,只能由该线程自己释放。
(3)请求和保持的条件:线程已经保持了一个 资源,但又提出了新的资源请求,而该资源被其他的线程所占用,此时请求进程被阻塞,但对自己的资源也不会释放。
(4)循环等待条件:存在一种线程资源的循环等待链,链中的每一个线程已获得的资源同时被链中下一个线程所请求。
三,产生死锁的一个例子
package com.itheima.gan; /** * 一个简单的死锁类 * @author 12428 * 当DeadLock类的对象flag==1时,(td1)先锁定o1,睡眠500毫秒 * 在td1睡眠的时候,另一个类对象的flag==0,(td2)线程启动,先锁定o2,睡眠500毫秒 * 静态属性是类的所有对象所共有的。 * 在td1睡眠结束的时候需要锁定o2才能继续执行,而此o2已被td2锁定 * td2 睡眠结束后需要锁定 o1 才能继续执行,而此时 o1 已被 td1 锁定; * td1、td2 相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。 * */ public class DeadLock implements Runnable{ public int flag=1; //静态对象是类的所有对象共享的 private static Object o1=new Object(),o2=new Object(); @Override public void run() { System.out.println("flag = "+flag); if(flag==1) { synchronized(o1) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2) { System.err.println("2"); } } } if(flag==0) { synchronized (o2) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1) { System.out.println("3"); } } } } public static void main(String[] args) { DeadLock td1=new DeadLock(); DeadLock td2=new DeadLock(); td1.flag=1; td2.flag=0; //td1,td2都处于可执行的状态,但虚拟机调用那个线程是未知的 new Thread(td1).start(); new Thread(td2).start(); } }
四,处理死锁的方法
(1)加锁的顺序(线程按照一定的顺序来加锁)
package com.itheima.gan; /* * 如何避免死锁 * 加锁的顺序 */ public class DeadLock2 { public int flag=1; //静态对象是类的所有对象共享的 private static Object o1=new Object(), o2=new Object(); public void money(int flag) { this.flag=flag; if(flag==1) { synchronized(o1) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(o2) { System.out.println("当前线程是"+Thread.currentThread().getName()+ " "+" flag的值是 :"+flag); } } } if(flag==0) { synchronized(o2) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(o1) { System.out.println("当前线程是"+Thread.currentThread().getName()+ " "+" flag的值是 :"+flag); } } } } public static void main(String[] args) { final DeadLock2 td1=new DeadLock2(); final DeadLock2 td2=new DeadLock2(); td1.flag=1; td2.flag=0; final Thread t1=new Thread(new Runnable() { @Override public void run() { td1.flag=1; td1.money(1); } }); t1.start(); Thread t2=new Thread(new Runnable() { @Override public void run() { try { //核心代码,让线程2在线程1执行完在执行,下面join方法的作用是当前线程放弃cpu的执行权,返回到t1线程执行的地方,直到t1线程执行完,再继续向下执行。 t1.join(); }catch (Exception e) { e.printStackTrace(); } td2.flag=0; //调用方法 td2.money(0); } }); t2.start(); } }