黑马程序员技术交流社区

标题: 死锁与死锁解决(面试会用到) [打印本页]

作者: 上篮高手    时间: 2013-10-19 11:49
标题: 死锁与死锁解决(面试会用到)
本帖最后由 上篮高手 于 2013-10-19 12:00 编辑

以下是一个会产生死锁的例子:
  1. package com.mingrisoft.thread;

  2. public class DeadLock implements Runnable {
  3.     private boolean flag;// 使用flag变量作为进入不同块的标志
  4.     private static final Object o1 = new Object();
  5.     private static final Object o2 = new Object();
  6.    
  7.     public void run() {
  8.         String threadName = Thread.currentThread().getName();// 获得当前线程的名字
  9.         System.out.println(threadName + ": flag = " + flag);// 输出当前线程的flag变量值
  10.         if (flag == true) {
  11.             synchronized (o1) {// 为o1加锁
  12.                 try {
  13.                     Thread.sleep(1000);// 线程休眠1秒钟
  14.                 } catch (InterruptedException e) {
  15.                     e.printStackTrace();
  16.                 }
  17.                 System.out.println(threadName + "进入同步块o1准备进入o2");// 显示进入o1块
  18.                 synchronized (o2) {// 为o2加锁
  19.                     System.out.println(threadName + "已经进入同步块o2");// 显示进入o2块
  20.                 }
  21.             }
  22.         }
  23.         if (flag == false) {
  24.             synchronized (o2) {
  25.                 try {
  26.                     Thread.sleep(1000);
  27.                 } catch (InterruptedException e) {
  28.                     e.printStackTrace();
  29.                 }
  30.                 System.out.println(threadName + "进入同步块o2准备进入o1");// 显示进入o2块
  31.                 synchronized (o1) {
  32.                     System.out.println(threadName + "已经进入同步块o1");// 显示进入o1块
  33.                 }
  34.             }
  35.         }
  36.     }
  37.    
  38.     public static void main(String[] args) {
  39.         DeadLock d1 = new DeadLock();// 创建DeadLock对象d1
  40.         DeadLock d2 = new DeadLock();// 创建DeadLock对象d2
  41.         d1.flag = true; // 将d1的flag设置为true
  42.         d2.flag = false; // 将d2的flag设置为false
  43.         new Thread(d1).start();// 在新线程中运行d1的run()方法
  44.         new Thread(d2).start();// 在新线程中运行d2的run()方法
  45.     }
  46. }
复制代码
Thread(d1)和  Thread(d2)启动后会分别进入不同的if 分支
此时Thread(d1) 占有锁01    Thread(d2) 占有锁o2
sleep后 Thread(d1) 会去请求资源o2   而 Thread(d2)会去请求资源o1
这样你不给我不让  就造成了死锁。


死锁的条件如下:
  1:    资源互斥(资源只能供一个线程使用)
  2:  请求保持(拥有资源的线程在请求新的资源又不释放占有的资源)
  3:  不能掠夺(已经获得的资源在使用完成前不能掠夺)
  4:  循环等待(各个线程对资源的需求构成一个循环)




以上例子的解决办法:
  1. public void run() {
  2.         String threadName = Thread.currentThread().getName();// 获得当前线程的名字
  3.         System.out.println(threadName + ": flag = " + flag);// 输出当前线程的flag变量值
  4.         if (flag == true) {
  5.             synchronized (o1) {// 为o1加锁
  6.                 try {
  7.                     Thread.sleep(1000);// 线程休眠1秒钟
  8.                 } catch (InterruptedException e) {
  9.                     e.printStackTrace();
  10.                 }
  11.                 System.out.println(threadName + "进入同步块o1准备进入o2");// 显示进入o1块
  12.                 System.out.println(threadName + "已经进入同步块o2");// 显示进入o2块<font color="#ff0000"><b>***********注意少了synchronized (o2) </b></font>
  13.             }
  14.             if (flag == false) {
  15.                 synchronized (o2) {
  16.                     try {
  17.                         Thread.sleep(1000);
  18.                     } catch (InterruptedException e) {
  19.                         e.printStackTrace();
  20.                     }
  21.                     System.out.println(threadName + "进入同步块o2准备进入o1");// 显示进入o2块
  22.                     synchronized (o1) {
  23.                         System.out.println(threadName + "已经进入同步块o1");// 显示进入o1块
  24.                     }
  25.                 }
  26.             }
  27.         }
复制代码
解决办法 : 对于这四个同步块,去掉任何一个就可以解决死锁的问题。



死锁的输出如下:Thread-0: flag = true
Thread-1: flag = false
Thread-1进入同步块o2准备进入o1
Thread-0进入同步块o1准备进入o2



作者: murder_fol    时间: 2013-10-19 12:53
思路很清晰  写很清楚 容易理解  谢谢




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2