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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 覃勇 初级黑马   /  2013-5-3 11:00  /  1342 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


/*
        以下这个例子是两个线程卖100张票
        两个线程一个线程运行同步代码块,一个线程运行同步函数,都执行买票动作
*/
  1. class Ticket implements Runnable
  2. {
  3.         private int Ticket=100;
  4.         boolean flag = true;
  5.         Object obj = new Object();
  6.         public void run()
  7.         {        if(flag)
  8.                 {
  9.                         while(true)
  10.                         {
  11.                                 synchronized(obj)        //可以验证同步的两个条件,一是多个线程,二是要是同一个锁,当不是同一个锁时,会出线0号票
  12.                                 {
  13.                                         if(Ticket>0)
  14.                                         {
  15.                                                 try{Thread.sleep(20);}catch (Exception e){}
  16.                                                 System.out.println(Thread.currentThread().getName()+"---"+(Ticket--));
  17.                                         }
  18.                                 }
  19.                         }
  20.                 }
  21.                 else
  22.                 {
  23.                         while(true)
  24.                         {
  25.                                 show();
  26.                         }
  27.                 }
  28.         }
  29.         public synchronized void show()                //用的this锁
  30.         {
  31.                 if(Ticket>0)
  32.                 {
  33.                         try{Thread.sleep(20);}catch (Exception e){}
  34.                         System.out.println(Thread.currentThread().getName()+"+++"+(Ticket--));
  35.                 }
  36.         }
  37. }
  38. class ThisLockDemo
  39. {
  40.         public static void main(String[] args)
  41.         {
  42.                 Ticket t = new Ticket();
  43.                 Thread t1 = new Thread(t);
  44.                 Thread t2 = new Thread(t);
  45.                 t1.start();
  46.                 try{Thread.sleep(5);}catch (Exception e){}        //首先明白这里一共有3个线程,主线程运行,当t1.start()启动后处于阻塞状态,有运行资格,但没有执行权,因为此时执行权在主线程,当主线程快速执行完之后,t1和t2去执行发现flag编程了false,所以都去执行show方法了。
  47.                 t.flag = false;                                                                        //加延迟时间是为了阻止主线程快速运行完毕。
  48.                 t2.start();
  49.                
  50.         }
  51. }
复制代码
首先明白:同步的条件有连个,一个是至少两个线程,二个是必须是同一个锁,
我的问题就是:当不是同一个锁时,程序出现了0号票,原理是什么

7 个回复

倒序浏览
出现0号票。
原理就是2个线程都执行了。
因为线程时时刻刻都是在抢cpu的执行权。
谁也不清楚什么时候是谁在执行。这是由cpu决定。
回复 使用道具 举报
你们都没说清楚,还是我自己来说吧:
首先我们来看一下结果:
D:\java>java ThisLockDemo
Thread-0---100
Thread-1+++99
Thread-0---98
Thread-1+++97
Thread-0---96
Thread-1+++95
Thread-0---94
Thread-1+++93
Thread-0---92
Thread-1+++91
Thread-0---90
Thread-1+++89
Thread-0---88
Thread-1+++87
Thread-0---86
Thread-1+++85
Thread-0---84
Thread-1+++83
Thread-0---82
Thread-1+++81
Thread-0---80
Thread-1+++79
Thread-0---78
Thread-1+++77
Thread-0---76
Thread-1+++75
Thread-0---74
Thread-1+++73
Thread-0---72
Thread-1+++71
Thread-0---70
Thread-1+++69
Thread-0---68
Thread-1+++67
Thread-0---66
Thread-1+++65
Thread-0---64
Thread-1+++63
Thread-0---62
Thread-1+++61
Thread-0---60
Thread-1+++59
Thread-0---58
Thread-1+++57
Thread-0---56
Thread-1+++55
Thread-0---54
Thread-1+++53
Thread-0---52
Thread-1+++51
Thread-0---50
Thread-1+++49
Thread-0---48
Thread-1+++47
Thread-0---46
Thread-1+++45
Thread-0---44
Thread-1+++43
Thread-0---42
Thread-1+++41
Thread-0---40
Thread-1+++39
Thread-0---38
Thread-1+++37
Thread-0---36
Thread-1+++35
Thread-0---34
Thread-1+++33
Thread-0---32
Thread-1+++31
Thread-0---30
Thread-1+++29
Thread-0---28
Thread-1+++27
Thread-0---26
Thread-1+++25
Thread-0---24
Thread-1+++23
Thread-0---22
Thread-1+++21
Thread-0---20
Thread-1+++19
Thread-0---18
Thread-1+++17
Thread-0---16
Thread-1+++15
Thread-0---14
Thread-1+++13
Thread-0---12
Thread-1+++11
Thread-0---10
Thread-1+++9
Thread-0---8
Thread-1+++7
Thread-0---6
Thread-1+++5
Thread-0---4
Thread-1+++3
Thread-0---2
Thread-1+++1
Thread-0---0
每次结果都是
Thread-0线程出现0号票
程序中关键位置是
  1.                                         if(Ticket>0)
  2.                                         {
  3.                                                 try{Thread.sleep(20);}catch (Exception e){}
  4.                                                 System.out.println(Thread.currentThread().getName()+"---"+(Ticket--));
  5.                                         }
复制代码
当Thicket为1的时候,线程0和线程1阻塞在冻结位置,都已经进入了Thicket>0的内部了,当线程1打印出1号票之后,线程0也就打印出了0号票。这就是为什么不同的锁出现了0号票,
但是另一个问题又产生了,经过我多次测验,每次都是线程0打印出0号票,这到底又是为什么呢??
回复 使用道具 举报
当不是同一把的时候,两个线程在最后交替执行过程中,t2 线程运行完后 show() 函数打印了1,而这时 t1 线程在开始的睡眠 sleep(20)中刚醒,然后接着执行刚刚没有完成的打印而此时的Tickt 已经为0了,所以会出现0号票。
回复 使用道具 举报
小羽天空 发表于 2013-5-3 13:01
当不是同一把的时候,两个线程在最后交替执行过程中,t2 线程运行完后 show() 函数打印了1,而这时 t1 线 ...

但是为什么每一次都是线程0出现0号票
回复 使用道具 举报
覃勇 发表于 2013-5-3 13:46
但是为什么每一次都是线程0出现0号票

那估计就是CPU自己的问题了,我不知道了,不好意思哈,兄弟帮不到你了。
回复 使用道具 举报
不知道LZ解决了没,每次都是线程0打印0号票的原因,其实是你程序sleep功能造成的,为什么会出现0号票楼主自己已经解决,就不说了。
0号票说明打印动作总共做了100+1次,而线程0每次都是第一个开始的(是主函数中sleep的缘故),那么1(线程0)、2(线程1)、3、4.....这样到100(线程1),最后就是线程0来卖这第101张票了,应该OK了吧,O(∩_∩)O~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马