“死锁”指的是:
多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。
因此, 某一个同步块需要同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题。下面案例中,“化妆线程”需要同时拥有“镜子对象”、“口红对象”才能运行同步块。那么,实际运行时,“小丫的化妆线程”拥有了“镜子对象”,“大丫的化妆线程”拥有了“口红对象”,都在互相等待对方释放资源,才能化妆。这样,两个线程就形成了互相等待,无法继续运行的“死锁状态”。
【示例1】死锁示例
class Lipstick{
} class Mirror{
}
class Makeup extends Thread { int flag; String girl; static Lipstick lipstick=new Lipstick(); static Mirror mirror= new Mirror();
@Override public void run() { // TODO Auto-generated method stub doMakeup(); } void doMakeup(){ if(flag==0){ synchronized (lipstick) { System.out.println(girl+"拿着口红!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (mirror) { System.out.println(girl+"拿着镜子!"); }
} } else{ synchronized (mirror) { System.out.println(girl+"拿着镜子!"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lipstick) { System.out.println(girl+"拿着口红!"); } } } }
}
public class TestDeadLock { public static void main(String[] args) { Makeup m1 = new Makeup(); m1.girl="大丫"; m1.flag=0; Makeup m2 = new Makeup(); m2.girl="小丫"; m2.flag=1; m1.start(); m2.start(); } } |
图1 线程互相等待“资源”而处于“停滞”状态
死锁的解决方法
死锁是由于“同步块需要同时持有多个对象锁造成”的,要解决这个问题,思路很简单,就是:
同一个代码块,不要同时持有两个对象锁。
如上面的死锁案例,修改成示例2所示。
【示例2】死锁问题的解决(修改示例1中doMakeup方法)
void doMakeup(){ if(flag==0){ synchronized (lipstick) { System.out.println(girl+"拿着口红!"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
} synchronized (mirror) { System.out.println(girl+"拿着镜子!"); } } else{ synchronized (mirror) { System.out.println(girl+"拿着镜子!"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (lipstick) { System.out.println(girl+"拿着口红!"); } } } |
「全栈Java笔记」是一部能帮大家从零到一成长为全栈Java工程师系列笔记。笔者江湖人称 Mr. G,10年Java研发经验,曾在神州数码、航天院某所研发中心从事软件设计及研发工作,从小白逐渐做到工程师、高级工程师、架构师。精通Java平台软件开发,精通JAVAEE,熟悉各种流行开发框架。
笔记包含从浅入深的六大部分:
A-Java入门阶段
B-数据库从入门到精通
C-手刃移动前端和Web前端
D-J2EE从了解到实战
E-Java高级框架精解
F-Linux和Hadoop