A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 官珺伟 高级黑马   /  2014-4-22 15:49  /  6321 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 官珺伟 于 2014-4-22 19:37 编辑

什么时候产生死锁,该怎么办?

点评

毕老师视频解疑惑!!!  发表于 2014-4-22 16:48

6 个回复

倒序浏览
死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它。

Java死锁范例
ThreadDeadlock.java

  1. package com.journaldev.threads;   public class ThreadDeadlock {       public static void main(String[] args) throws InterruptedException {         Object obj1 = new Object();         Object obj2 = new Object();         Object obj3 = new Object();           Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");         Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");         Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");           t1.start();         Thread.sleep(5000);         t2.start();         Thread.sleep(5000);         t3.start();       }   }   class SyncThread implements Runnable{     private Object obj1;     private Object obj2;       public SyncThread(Object o1, Object o2){         this.obj1=o1;         this.obj2=o2;     }     @Override    public void run() {         String name = Thread.currentThread().getName();         System.out.println(name + " acquiring lock on "+obj1);         synchronized (obj1) {          System.out.println(name + " acquired lock on "+obj1);          work();          System.out.println(name + " acquiring lock on "+obj2);          synchronized (obj2) {             System.out.println(name + " acquired lock on "+obj2);             work();         }          System.out.println(name + " released lock on "+obj2);         }         System.out.println(name + " released lock on "+obj1);         System.out.println(name + " finished execution.");     }     private void work() {         try {             Thread.sleep(30000);         } catch (InterruptedException e) {             e.printStackTrace();         }     } }
复制代码

在上面的程序中同步线程正完成Runnable的接口,它工作的是两个对象,这两个对象向对方寻求死锁而且都在使用同步阻塞。

在主函数中,使用了三个为同步线程运行的线程,而且在其中每个线程中都有一个可共享的资源。

这些线程以向第一个对象获取封锁这种方式运行。但是当它试着像第二个对象获取封锁时,它就会进入等待状态,因为它已经被另一个线程封锁住了。这样,在线程引起死锁的过程中,就形成了一个依赖于资源的循环。

当执行上面的程序时,就产生了输出,但是程序却因为死锁无法停止。
避免死锁
有很多方针可供我们使用来避免死锁的局面。

•避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。例如,这里是另一个运行中没有嵌套封锁的run()方法,而且程序运行没有死锁局面,运行得很成功。
1234567891011121314151617 public void run() {     String name = Thread.currentThread().getName();     System.out.println(name + " acquiring lock on " + obj1);     synchronized (obj1) {         System.out.println(name + " acquired lock on " + obj1);         work();     }     System.out.println(name + " released lock on " + obj1);     System.out.println(name + " acquiring lock on " + obj2);     synchronized (obj2) {         System.out.println(name + " acquired lock on " + obj2);         work();     }     System.out.println(name + " released lock on " + obj2);       System.out.println(name + " finished execution."); }
•只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。
•避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。


回复 使用道具 举报 1 0
死锁是指这样一种情况:多个线程同时被阻塞,它们中的一个或者全部在等待某个资源被释放或者是都是处于等待而无法被唤醒时,由于线程被无限地阻塞,因此程序不能正常终止。
产生死锁的原因主要有:1、临界资源使用的互斥性。2、部分地分配资源。3、资源的循环等待。4、资源的不可抢占性等。java技术不能发现死锁也不能避免死锁。解决办法是编写代码时应注意死锁问题,尽量避免。下面是死锁的例子
  1. public class TestDeadLock implements Runnable
  2.         {
  3.                 public int flag = 1;
  4.                 public static Object o1 = new Object();
  5.                 public static Object o2 = new Object();

  6.                 public void run()
  7.                         {
  8.                                 System.out.println("flag:" + flag);
  9.                                 if (flag == 1)
  10.                                         {
  11.                                                 synchronized (o1)
  12.                                                         {
  13.                                                                 try
  14.                                                                         {
  15.                                                                                 Thread.sleep(10);
  16.                                                                         } catch (InterruptedException e)
  17.                                                                         {
  18.                                                                                 e.printStackTrace();
  19.                                                                         }
  20.                                                                 synchronized (o2)
  21.                                                                         {
  22.                                                                                 System.out.println("111");
  23.                                                                         }
  24.                                                         }

  25.                                         } else if (flag == 0)
  26.                                         {
  27.                                                 synchronized (o2)
  28.                                                         {
  29.                                                                 try
  30.                                                                         {
  31.                                                                                 Thread.sleep(10);
  32.                                                                         } catch (InterruptedException e)
  33.                                                                         {
  34.                                                                                 e.printStackTrace();
  35.                                                                         }
  36.                                                                 synchronized (o1)
  37.                                                                         {
  38.                                                                                 System.out.println("000");
  39.                                                                         }
  40.                                                         }
  41.                                         }
  42.                         }
  43.                 public static void main(String[] args)
  44.                         {
  45.                                 TestDeadLock td1 = new TestDeadLock();
  46.                                 TestDeadLock td2 = new TestDeadLock();
  47.                                 td1.flag = 1;
  48.                                 td2.flag = 0;
  49.                                 Thread t1 = new Thread(td1);
  50.                                 Thread t2 = new Thread(td2);
  51.                                 t1.start();
  52.                                 t2.start();
  53.                         }
  54.         }
复制代码
回复 使用道具 举报
在多线程中,用到锁嵌套,写成死锁了,该如何解锁呢?
回复 使用道具 举报
阿旺 发表于 2014-4-22 15:55
死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源 ...

你好,我是一个中学生,麻烦你告诉我,这个你提供的这个java死锁范例发生时,CPU占用率是高还是低?阻塞的线程占用CPU时间,但没有产生新的运算操作,这个时候CPU也出于繁忙的运算状态?
回复 使用道具 举报
z1342802487 发表于 2014-4-22 17:43
死锁是指这样一种情况:多个线程同时被阻塞,它们中的一个或者全部在等待某个资源被释放或者是都是处于等待 ...

别笑我,问个同样的问题,这个你提供的这个java死锁范例发生时,CPU占用率是高还是低?阻塞的线程占用CPU时间,但没有产生新的运算操作,这个时候CPU也出于繁忙的运算状态?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马