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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© hdsjsql 中级黑马   /  2013-4-20 10:50  /  1809 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 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, 下载次数: 26)

死锁1.png

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

死锁2.png

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

11 个回复

倒序浏览
注释后,其实也能发生死锁的,只是cpu在进行线程切换时,t2线程还没执行时,t1这个线程已经执行完了。你若想试试,你可以把静态变量tick的值改为Integer.MAX_VALUE,然后再试试。
try{Thread.sleep(10);}catch(Exception e){}  这个是让当前线程休眠,这时,cpu就会切换到其他线程去了。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
先小涛 发表于 2013-4-20 10:58
注释后,其实也能发生死锁的,只是cpu在进行线程切换时,t2线程还没执行时,t1这个线程已经执行完了。你若 ...

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

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

死锁1.png

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

死锁2.png
回复 使用道具 举报
hdsjsql 发表于 2013-4-20 12:01
线程t1,t2都以运行,见图,

我试了你的程序,没有发生死锁哈,你运行会发生死锁吗?死锁的原因是要有两个锁,并且线程之间同时要各自拿到一个锁,并且需要另一个锁,这时才有可能发生死锁。而你的程序里只有一个锁是obj,所以不会发生死锁的。
回复 使用道具 举报
本帖最后由 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, 下载次数: 24)

死锁3.png
回复 使用道具 举报
hdsjsql 发表于 2013-4-20 13:23
如果保留这句try{Thread.sleep(10);}catch(Exception e){} ,一定会发生死锁,
程序中有两个锁,同步代码块 ...

怪事了,你的程序运行了n遍,加注释,和没加注释都是一样滴
回复 使用道具 举报
先小涛 发表于 2013-4-20 13:35
怪事了,你的程序运行了n遍,加注释,和没加注释都是一样滴

不是加不加注释,而是保不保留代码try{Thread.sleep(10);}catch(Exception e){}
回复 使用道具 举报
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。   先前是我理解差了,抱歉了。
回复 使用道具 举报
先小涛 发表于 2013-4-20 13:52
try{Thread.sleep(10);}catch(Exception e){}  
其作用是:让主线程也就是main方法休眠,这样的话当t1线程 ...

还是不太明白,去掉try{Thread.sleep(10);}catch(Exception e){}  后为什么不死锁
这时线程t1,t2都以运行,且同步中存在嵌套
回复 使用道具 举报
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: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();
复制代码
回复 使用道具 举报
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)
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马