黑马程序员技术交流社区

标题: 关于多线程的问题 [打印本页]

作者: 杜成龙    时间: 2013-6-12 20:14
标题: 关于多线程的问题
本帖最后由 杜成龙 于 2013-6-13 16:56 编辑
  1. class Ticket implements Runnable
  2. {
  3.         int tick=100;
  4.         boolean flag=true;
  5.         Object obj=new Object();
  6.         public void run()
  7.        {
  8.             if(flag)
  9.            {
  10.                 while(true)
  11.                  {
  12.                      synchronized(obj)
  13.                     {
  14.                          if(tick>0)
  15.                          {
  16.                             try{Thread.sleep(10);}catch(Exception e){}
  17.                             System.out.println(Thread.currentThread().getName()+" code"+tick--);
  18.                          }
  19.                     }
  20.                 }
  21.            }
  22.          else
  23.           while(true)
  24.            show();
  25.      }

  26. public synchronized void show()
  27.   {
  28.         if(tick>0)
  29.        {
  30.            try{Thread.sleep(10);}catch(Exception e){}
  31.             System.out.println(Thread.currentThread().getName()+" show"+tick--);
  32.         }
  33.   }
  34. }
  35. class TicketDemo4
  36. {
  37.       public static void main(String[] args)
  38.       {
  39.            Ticket t=new Ticket();
  40.            Thread t1=new Thread(t);
  41.            Thread t2=new Thread(t);
  42.             t1.start();
  43.            try{Thread.sleep(10);}catch(Exception e){}
  44.            t.flag=false;
  45.            t2.start();
  46.       }
  47. }
复制代码
程序的运行结果有些疑惑,想请教一下,
当程序中执行t.flag=false后,就把flag改成了false状态了,按说线程就不会执行同步代码块中的内容了,会去执行同步函数中的内容,
但是为什么运行的结果中在出现Thread-1后又会出现Thread-0呢?还有就是t2开启后,t1也还是开启的,按说t1也能进入同步函数中去执行,为什么
同步函数中只有t2线程,也就是Thread-1线程呢?(注:t1线程对应的是Thread-0线程,t2线程对应的是Thread-1线程)


作者: ying_1990    时间: 2013-6-12 23:19
class TicketDemo4
{
      public static void main(String[] args)
      {
           Ticket t=new Ticket();
           Thread t1=new Thread(t);
           Thread t2=new Thread(t);
            t1.start();
           //try{Thread.sleep(10);}catch(Exception e){}   //试试将该句注释掉,是不是你想要的结果?
           t.flag=false;
           t2.start();
      }
}

作者: 小冰块    时间: 2013-6-12 23:21
本帖最后由 小冰块 于 2013-6-12 23:37 编辑

亲,其实你这两个问题都是一个问题,那就是为什么T1始终在同步代码块中,而T2始终在同步函数中。

你看,刚开始的时候flag是true,T1先跑,趁着主线程睡觉的时候进入到了同步代码块code中,然后T2等醒来的时候发现flag已经变成了false,所以只能去同步函数show中,然后他们一直保持在这样的一个状态里。

为什么会一直保持这样的状态呢?因为你的T1自从判断过一个flag=true并进入代码块中后,就再也没出过代码块中的while循环(因为while始终为true),所以就再也没有判断该flag。

同样的,你的show函数的前提也是while(true),所以T2就一直在同步函数中,两个线程就各自在各自的地盘互不干扰的玩了。

另外帮你改了一下程序,这样T1和T2可以随机的进出同步代码块和同步函数,而不破坏同步性:
  1. class Ticket implements Runnable
  2. {
  3.         int tick=100;
  4.         boolean flag=true;
  5.         Object obj=new Object();
  6.         public void run()
  7.        {
  8.          while(true)      //把while定义到if和else的外面,而不是只循环if
  9.           {        
  10.                if(flag)          //内层循环去掉,每次输出一次后都会重回while的顶端重新判断if(flag)
  11.                {
  12.                 synchronized(obj)
  13.                      {
  14.                      if(tick>0)
  15.                      {
  16.                          try{Thread.sleep(10);}catch(Exception e){}
  17.                          System.out.println(Thread.currentThread().getName()+" code"+tick--);

  18.                           flag = false;        //如果进来的时候状态是true,卖掉一张票后改变标记
  19.                           }
  20.                       }
  21.                 }
  22.          else         
  23.            show();
  24.        }
  25. }

  26. public synchronized void show()
  27.   {
  28.         if(tick>0)
  29.        {
  30.            try{Thread.sleep(10);}catch(Exception e){}
  31.             System.out.println(Thread.currentThread().getName()+" show"+tick--);
  32.              flag = true;         //同样要记得改变标记,不然标记就固定死了               
  33.         }
  34.   }
  35. }
  36. class TicketDemo4
  37. {
  38.       public static void main(String[] args)
  39.       {
  40.            Ticket t=new Ticket();
  41.            Thread t1=new Thread(t);
  42.            Thread t2=new Thread(t);
  43.             t1.start();
  44.            try{Thread.sleep(10);}catch(Exception e){}
  45.            t.flag=false;
  46.            t2.start();
  47.       }
  48. }
复制代码

作者: ying_1990    时间: 2013-6-12 23:41
学习了,论坛果然暗藏高手,多逛论坛可以学到更多知识{:soso_e128:}
作者: 孙百鑫    时间: 2013-6-13 06:37
楼主您好!如果问题得到解决请将题目改成"已解决"
编辑文章-->修改 如果问题没有得到解决请继续发问谢谢您的配合{:soso_e100:}
作者: 杜成龙    时间: 2013-6-13 17:21
小冰块 发表于 2013-6-12 23:21
亲,其实你这两个问题都是一个问题,那就是为什么T1始终在同步代码块中,而T2始终在同步函数中。

你看,刚 ...

受教了,谢谢啦~{:soso_e100:}




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