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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ぺsimon☆ 中级黑马   /  2013-5-16 00:04  /  1103 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 ぺsimon☆ 于 2013-5-16 08:47 编辑
  1. /*
  2. 继承Thread类做一个卖票程序

  3. 为什么程序的运行结果有0号票呢,哥们?
  4. */

  5. class Ticket extends Thread
  6. {
  7.         private static int ticket=100;
  8.         Object obj=new Object();

  9.         public void run()
  10.         {
  11.         while(true)
  12.         {

  13.         synchronized(obj)
  14.         {
  15.         if(ticket>0)
  16.         {
  17.         try{Thread.sleep(10);}catch(Exception e){}
  18.         System.out.println(Thread.currentThread().getName()+"..."+ticket--);
  19.         }
  20.         }
  21.         }
  22.         }
  23. }

  24. class TicketOne
  25. {
  26.         public static void main(String[] args)
  27.         {
  28.         Ticket t1=new Ticket();
  29.         t1.start();

  30.         Ticket t2=new Ticket();
  31.         t2.start();
  32.         }
  33. }
复制代码

6 个回复

倒序浏览
{:soso_e140:}真不知道还是假不知道啊
回复 使用道具 举报
刘学明    发表于 2013-5-16 00:13
真不知道还是假不知道啊

是真不知道啊,哥们
回复 使用道具 举报
为什么出现0?
因为t1和t2持有不同的锁。t1和t2分别new了自己Object对象,因此synchronized(obj)持有的锁是不同的,假设当Thread-o执行到ticket=1时,if(ticket>0),满足,然后sleep(10)睡一会儿,此时Thread-1抢到执行权,通过ticket--打印1,并将ticket改为0,这时Thread睡醒了,拿着值为0的ticket输出了!
解决办法:1. 将两条线程的锁同步,可将Object变量改为静态的,即static Object obj=new Object();
               2.把if(ticket>0),改为while(ticket>0),每个线程睡醒后都要判断ticket的值。
回复 使用道具 举报
此程序的第33和36行分别创建了两个Ticket对象 t1和t2.
每个Ticket对象中都有一个私有的 ticket =100. 这就相当于有了200张票。
而且每个对象都有一个  obj 对象  这就使得线程使用的锁不是同一个锁。
所以就出现了 同样的票被卖了两次和出现0号票的情况
修改后的主函数代码
public static void main(String[] args)
{  
       Ticket t = new Ticket();   //创建一个Ticket对象,保证了资源(票)的唯一,和锁的唯一;

       Thread t1 = new Thread(t);     //创建两个线程,操作同一个资源(票)使用的也是同一个锁obj;

       Thread t2 = new Thread(t);

        t1.start();

        t2.start();
}
回复 使用道具 举报
看来我对多线程掌握得真的不是那么好啊,谢谢大家的解答,我明白了
回复 使用道具 举报
ak1234 中级黑马 2013-5-16 09:23:47
7#
本帖最后由 ak1234 于 2013-5-16 09:27 编辑

class Ticket extends Thread{
        private static int ticket=100;

        public void run(){
                while(ticket > 0){
                       synchronized(this){
                                if(ticket == 0)break;
                                        System.out.println(Thread.currentThread().getName()+"..."+ticket--);
                                }
                        try{
                                Thread.sleep(1);
                                }
                        catch(Exception e){
                                }
                        }
               }
}

class TicketOne
{
        public static void main(String[] args)
        {
        Ticket t=new Ticket();
        Thread t1 = new Thread(t);

        Thread t2 = new Thread(t);

        t1.start();

        t2.start();
        }
}
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马