黑马程序员技术交流社区

标题: 关于多线程ThisLock这一节的问题。 [打印本页]

作者: 陈雪琪    时间: 2013-5-3 10:57
标题: 关于多线程ThisLock这一节的问题。
本帖最后由 陈雪琪 于 2013-5-3 13:10 编辑
  1. class ThisLockDemo
  2. {
  3.         public static void main(String[] args){
  4.                 Ticket t=new Ticket();
  5.                 Thread t1=new Thread(t);
  6.                 Thread t2=new Thread(t);
  7.                 t1.start();
  8.                 try{Thread.sleep(10);}catch(Exception e){}
  9.                 t.flag=false;
  10.                 t2.start();
  11.         }
  12. }
  13. class Ticket implements Runnable
  14. {
  15.         private int num=100;
  16.         Object obj=new Object();
  17.         boolean flag=true;
  18.         public  void run(){
  19.                 if(flag){
  20.                         while(true){
  21.                                 synchronized(obj){
  22.                                         if(num>0){
  23.                                                 try{Thread.sleep(10);}
  24.                                                 catch(InterruptedException e){}
  25.                                                 System.out.println(Thread.currentThread().getName()+"sale.."+num--);
  26.                                         }
  27.                
  28.                                 }
  29.                         }
  30.                 }
  31.                 else
  32.                         while(true)
  33.                                 show();
  34.         }
  35.         
  36.         public synchronized void show(){
  37.                 if(num>0){
  38.                         try{Thread.sleep(10);}
  39.                         catch(InterruptedException e){}
  40.                         System.out.println(Thread.currentThread().getName()+"showshow........"+num--);
  41.                 }
  42.         }
  43.         
  44. }
复制代码
这段代码的运行结果是(只截取了一小部分)

问题:
为什么Thread-0线程一直打印的都是同步代码块中的sale。虽然老师说让主线程睡一会,先不让flag变为false。可是当主线程醒了后flag就会变成false了啊,这个时候Thread-0就应该执行的是同步函数show方法中的内容了,应该要打印showshow才是吧?为什么还是直到最后都是打印sale呢?

PS:刚学到这,现在该程序是不安全的,暂且不纠结程序的安全问题。


捕获.PNG (14.3 KB, 下载次数: 0)

运行结果(截取的是前半部分)

运行结果(截取的是前半部分)

作者: 曹德君    时间: 2013-5-3 11:59
本帖最后由 曹德君 于 2013-5-3 12:04 编辑

是这样子的,Thread0开启线程 flag为ture ,进如while循环体而他的的条件一直为真,没有跳出循环体。thread1开启后检查flag为false就去运行show了。
  1. class ThisLockDemo
  2. {
  3.         public static void main(String[] args){
  4.                 Ticket t=new Ticket();
  5.                 Thread t1=new Thread(t);
  6.                 Thread t2=new Thread(t);
  7.                 t1.start();
  8.                 try{Thread.sleep(10);}catch(Exception e){}
  9.                 t.flag=false;
  10.                 t2.start();
  11.         }
  12. }
  13. class Ticket implements Runnable
  14. {
  15.         private int num=100;
  16.         Object obj=new Object();
  17.         boolean flag=true;
  18.         public  void run(){
  19.                 if(flag){
  20.                         while(flag){//此处的while循环条件换成flag可以应该可以达到你想要的效果。
  21.                                 synchronized(obj){
  22.                                         if(num>0){
  23.                                                 try{Thread.sleep(10);}
  24.                                                 catch(InterruptedException e){}
  25.                                                 System.out.println(Thread.currentThread().getName()+"sale.."+num--);
  26.                                         }
  27.                
  28.                                 }
  29.                         }
  30.                 }
  31.                 else
  32.                         while(true)
  33.                                 show();
  34.         }
  35.         
  36.         public synchronized void show(){
  37.                 if(num>0){
  38.                         try{Thread.sleep(10);}
  39.                         catch(InterruptedException e){}
  40.                         System.out.println(Thread.currentThread().getName()+"showshow........"+num--);
  41.                 }
  42.         }
  43.         
  44. }
复制代码

作者: 黑马华    时间: 2013-5-3 12:05
本帖最后由 黑马华 于 2013-5-3 12:08 编辑

这个你一开始运行的线程t1就去运行run方法了,它一直在内部运行,不会再一次判断flag,所以后面那个flag只会影响线程t2
调用run方法再调用show方法。所以thread0只会显示sale,thread1只会显示showshow
作者: 赵崇友    时间: 2013-5-3 13:00
因为当Thread0线程开启后,判读flag为ture,进入执行下面的代码块,又因为while的条件一直为true,所以会一直循环执行代码块中的了,所以一直打印的是sale。当Thread1线程开启后,判断flag为false所以会执行同步函数内的内容,而同步函数里还是一个死循环,一直会打印showshow了。而且发现您的同步代码块和同步函数使用的不是同一个锁。
  1. class ThisLockDemo
  2. {
  3.         public static void main(String[] args){
  4.                 Ticket t=new Ticket();
  5.                 Thread t1=new Thread(t);
  6.                 Thread t2=new Thread(t);
  7.                 t1.start();
  8.                 try{Thread.sleep(10);}catch(Exception e){}
  9.                 t.flag=false;
  10.                 t2.start();
  11.         }
  12. }
  13. class Ticket implements Runnable
  14. {
  15.         private int num=100;
  16.         Object obj=new Object();
  17.         boolean flag=true;
  18.         public  void run(){
  19.                 if(flag){
  20.                         while(true){
  21.                                 synchronized(obj){
  22.                                         if(num>0){
  23.                                                 try{Thread.sleep(10);}
  24.                                                 catch(InterruptedException e){}
  25.                                                 System.out.println(Thread.currentThread().getName()+"sale.."+num--);
  26.                                         }
  27.                
  28.                                 }
  29.                         }
  30.                 }
  31.                 else
  32.                         while(true)
  33.                                 show();
  34.         }
  35.         
  36.         public synchronized void show(){
  37.                 if(num>0){
  38.                         try{Thread.sleep(10);}
  39.                         catch(InterruptedException e){}
  40.                         System.out.println(Thread.currentThread().getName()+"showshow........"+num--);
  41.                 }
  42.         }
  43.         
  44. }
复制代码

作者: 陈雪琪    时间: 2013-5-3 13:19
曹德君 发表于 2013-5-3 11:59
是这样子的,Thread0开启线程 flag为ture ,进如while循环体而他的的条件一直为真,没有跳出循环体。thread ...

谢谢咯 终于知道是while循环体没有被跳出的原因。只是你修改代码标出注释的地方好像有点小问题噢  如果我换成flag的话  Thread0线程运行一下后就不运行了   好像是因为while循环为false后,就跳出了循环。只有Thread1线程一直在运行。不知道有没有说错额~~~
作者: 陈雪琪    时间: 2013-5-3 13:20
黑马华 发表于 2013-5-3 12:05
这个你一开始运行的线程t1就去运行run方法了,它一直在内部运行,不会再一次判断flag,所以后面那个flag只 ...

谢谢指点咯~~




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