黑马程序员技术交流社区

标题: 关于死锁的问题 [打印本页]

作者: hdsjsql    时间: 2013-4-20 10:50
标题: 关于死锁的问题
本帖最后由 hdsjsql 于 2013-4-21 15:58 编辑

程序原本会死锁,注释掉try{Thread.sleep(10);}catch(Exception e){}则不会发生死锁.实在看不出这句代码对死锁有什么影响.运行过程中,ti,t2都以运行.
  1. class Ticket implements Runnable
  2. {
  3.         
  4.         private  static int tick = 1000;
  5.         Object obj = new Object();
  6.         boolean flag = true;
  7.         public  void run()
  8.         {
  9.                 if(flag)
  10.                 {
  11.                         while(true)
  12.                         {
  13.                                 synchronized(obj)
  14.                                 {
  15.                                 
  16.                                         if(tick>0)
  17.                                         {
  18.                                                 show();
  19.                                         }
  20.                                 }
  21.                         }
  22.                 }
  23.                 else
  24.                         while(true)
  25.                                 show();
  26.         }
  27.         public synchronized   void show()//this
  28.         {
  29.                 synchronized(obj)
  30.                 {
  31.                 if(tick>0)
  32.                 {
  33.                         try{Thread.sleep(10);}catch(Exception e){}
  34.                         System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
  35.                 }
  36.           }
  37.         }
  38. }


  39. public class  ThisLockDemo
  40. {
  41.         public static void main(String[] args)
  42.         {

  43.                 Ticket t = new Ticket();

  44.                 Thread t1 = new Thread(t);
  45.                 Thread t2 = new Thread(t);
  46.                 t1.start();
  47.                 //try{Thread.sleep(10);}catch(Exception e){}  //注释掉这句,不会发生死锁,不注释则会死锁.求解.
  48.                 t.flag = false;
  49.                 t2.start();
  50.         }
  51. }
复制代码

死锁1.png (2.92 KB, 下载次数: 27)

死锁1.png

死锁2.png (4.09 KB, 下载次数: 21)

死锁2.png

作者: 先小涛    时间: 2013-4-20 10:58
注释后,其实也能发生死锁的,只是cpu在进行线程切换时,t2线程还没执行时,t1这个线程已经执行完了。你若想试试,你可以把静态变量tick的值改为Integer.MAX_VALUE,然后再试试。
try{Thread.sleep(10);}catch(Exception e){}  这个是让当前线程休眠,这时,cpu就会切换到其他线程去了。
作者: hdsjsql    时间: 2013-4-20 12:01
先小涛 发表于 2013-4-20 10:58
注释后,其实也能发生死锁的,只是cpu在进行线程切换时,t2线程还没执行时,t1这个线程已经执行完了。你若 ...

线程t1,t2都以运行,见图,

死锁1.png (2.92 KB, 下载次数: 38)

死锁1.png

死锁2.png (4.09 KB, 下载次数: 25)

死锁2.png

作者: 先小涛    时间: 2013-4-20 13:18
hdsjsql 发表于 2013-4-20 12:01
线程t1,t2都以运行,见图,

我试了你的程序,没有发生死锁哈,你运行会发生死锁吗?死锁的原因是要有两个锁,并且线程之间同时要各自拿到一个锁,并且需要另一个锁,这时才有可能发生死锁。而你的程序里只有一个锁是obj,所以不会发生死锁的。
作者: hdsjsql    时间: 2013-4-20 13:23
本帖最后由 hdsjsql 于 2013-4-20 13:35 编辑
先小涛 发表于 2013-4-20 13:18
我试了你的程序,没有发生死锁哈,你运行会发生死锁吗?死锁的原因是要有两个锁,并且线程之间同时要各自 ...

如果保留这句try{Thread.sleep(10);}catch(Exception e){} ,一定会发生死锁,
程序中有两个锁,同步代码块的锁为obj,同步函数为this

死锁3.png (28.21 KB, 下载次数: 26)

死锁3.png

作者: 先小涛    时间: 2013-4-20 13:35
hdsjsql 发表于 2013-4-20 13:23
如果保留这句try{Thread.sleep(10);}catch(Exception e){} ,一定会发生死锁,
程序中有两个锁,同步代码块 ...

怪事了,你的程序运行了n遍,加注释,和没加注释都是一样滴
作者: hdsjsql    时间: 2013-4-20 13:37
先小涛 发表于 2013-4-20 13:35
怪事了,你的程序运行了n遍,加注释,和没加注释都是一样滴

不是加不加注释,而是保不保留代码try{Thread.sleep(10);}catch(Exception e){}
作者: 先小涛    时间: 2013-4-20 13:52
try{Thread.sleep(10);}catch(Exception e){}  
其作用是:让主线程也就是main方法休眠,这样的话当t1线程启动后,才执行t.flag = false;这句。这样的话,t1和t2两个线程才能交替执行。重点在于t.flag = false要稍后执行,不然主线程是执行t1.start()后会立即执行t.flag = false;这样,那么t1和t2两个线程中的flag都是false。   先前是我理解差了,抱歉了。
作者: hdsjsql    时间: 2013-4-20 14:01
先小涛 发表于 2013-4-20 13:52
try{Thread.sleep(10);}catch(Exception e){}  
其作用是:让主线程也就是main方法休眠,这样的话当t1线程 ...

还是不太明白,去掉try{Thread.sleep(10);}catch(Exception e){}  后为什么不死锁
这时线程t1,t2都以运行,且同步中存在嵌套
作者: 先小涛    时间: 2013-4-20 16:31
hdsjsql 发表于 2013-4-20 14:01
还是不太明白,去掉try{Thread.sleep(10);}catch(Exception e){}  后为什么不死锁
这时线程t1,t2都以运 ...

flag值都是false,他们运行的都是run方法里面的else内容,运行的都是show方法。不信得话,你可以在if语句块里加上打印语句, 你看有没有打印输出。
作者: hdsjsql    时间: 2013-4-20 20:03
本帖最后由 hdsjsql 于 2013-4-20 20:05 编辑
先小涛 发表于 2013-4-20 16:31
flag值都是false,他们运行的都是run方法里面的else内容,运行的都是show方法。不信得话,你可以在if语句 ...

flag为true时也会运行show()方法,
  1. if(flag)
  2.                 {
  3.                         while(true)
  4.                         {
  5.                                 synchronized(obj)
  6.                                 {
  7.                                 
  8.                                         if(tick>0)
  9.                                         {
  10.                                                 show();
复制代码

作者: 先小涛    时间: 2013-4-21 12:03
hdsjsql 发表于 2013-4-20 20:03
flag为true时也会运行show()方法,

这个程序中的flag的作用是让t1线程走if语句,然后设置flag为true,这样就让t2线程走else语句了。而现在由于main方法不休眠的话会瞬间执行flag=true这句,所以他们都会走else语句中的内容,也就是他们都是直接调用show方法,由于show方法加了synchronized字段,他们的锁都是this,所以他们是同步的。而if里则加了synchronized(obj){}语句块,也就是加了另一锁(obj)




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