解决方案 »

  1.   


    public class Ticket implements Runnable {
     
        private int ticket = 5;
     
        public void run() {
           
     
                while (true)
                  synchronized (this) 
                  {
                    if (ticket > 0) 
                    {
                        System.out.println("顾客到达 "
                                + Thread.currentThread().getName() + "售票台");
                        System.out.println("售票台" + Thread.currentThread().getName()
                                + "准备出售第" + ticket + "张票");
                        try 
                        {// 具体卖票过程
                            /*System.out.println("售票台需要5分钟出售这张票");
                            for (int i = 1; i < 5; i++) {
                                Thread.sleep(1000);
                                System.out.println(i + "分钟");
                            }*/
                            System.out.println("售票台"
                                    + Thread.currentThread().getName() + "卖完第"
                                    + ticket + "张票");
                            System.out.println("顾客从"
                                    + Thread.currentThread().getName() + "买到第"
                                    + ticket + "张票");
                            ticket--;
                        } 
                        catch (Exception e) 
                        {
                            System.out.println("卖票不成功");
                            System.exit(1);
                        }
                    } 
                   
                    else 
                    {
                        break;
                    }
                
           }
        }
        
        public static void main(String[] args) {
            Ticket t = new Ticket();
             Thread s = new Thread(t);
             Thread s1 = new Thread(t);
             Thread s2 = new Thread(t);
             Thread s3 = new Thread(t);
             s.start();
             s1.start();
             s2.start();
             s3.start();
     
        }
     
    }稍做了一下修改 这个是同步问题 错票 负票都是没上锁的原因 
      

  2.   

    其实你两个程序都一样有问题,至于你第二个问题没有体现出来是因为时间太短了。
    第一个里面有sleep,第二个却没有,如果第二个把sleep加上的话,效果会是一样的。按照1楼的方式加锁是可以的。只不过这个锁加的范围有点大了,这样就和单线程没有区别了。可以对程序做一些调整,适当减小加锁的范围。
      

  3.   

    楼主一开始的两个程序,都是多线程去抢ticket,不上锁肯定会冲突的,楼上说得对,第二个没有出现负数是因为时间太短而已!  
    试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。
    所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread {
     
        private volatile int ticket = 5;
        private volatile int ticketControl = ticket;
     
        @Override
        public void run() {
            while (true) {
                if (ticketControl-- > 0) {
                    System.out.println("顾客到达 "
                            + Thread.currentThread().getName() + "售票台");
                    System.out.println("售票台" + Thread.currentThread().getName()
                            + "准备出售第" + ticket + "张票");
                    try {// 具体卖票过程
                        System.out.println("售票台需要5分钟出售这张票");
                        for (int i = 1; i < 5; i++) {
                            Thread.sleep(100);
                            System.out.println(i + "分钟");
                        }
                        System.out.println("售票台"
                                + Thread.currentThread().getName() + "卖完第"
                                + ticket + "张票");
                        System.out.println("顾客从"
                                + Thread.currentThread().getName() + "买到第"
                                + ticket + "张票");
                        --ticket;
                    } catch (InterruptedException e) {
                        System.out.println("卖票不成功");
                        System.exit(1);
                    }
                } else {
                    break;
                }
            }
        }
    }
      

  4.   

    我再补充一下,由于“if (ticketControl-- > 0) {”不是原子操作,其实还是有冲突的隐患,所以再加个锁更加稳妥,而且也不怎么影响性能,改成如下:int nTicket = 0;
             synchronized(this) {
             nTicket = ticketControl--;
             }
                if (nTicket > 0) {
      

  5.   

    的二个是人品好  多运行几次总会出负的  第一个因为有sleep所以隐患比较明显罢了
      

  6.   


    当我把第一个的sleep去掉后还是有负票,当我把第二个票数改到2000的时候,还是没有负票。
      

  7.   

    楼主一开始的两个程序,都是多线程去抢ticket,不上锁肯定会冲突的,楼上说得对,第二个没有出现负数是因为时间太短而已!  
    试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。
    所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread {
     
        private volatile int ticket = 5;
        private volatile int ticketControl = ticket;
     
        @Override
        public void run() {
            while (true) {
                if (ticketControl-- > 0) {
                    System.out.println("顾客到达 "
                            + Thread.currentThread().getName() + "售票台");
                    System.out.println("售票台" + Thread.currentThread().getName()
                            + "准备出售第" + ticket + "张票");
                    try {// 具体卖票过程
                        System.out.println("售票台需要5分钟出售这张票");
                        for (int i = 1; i < 5; i++) {
                            Thread.sleep(100);
                            System.out.println(i + "分钟");
                        }
                        System.out.println("售票台"
                                + Thread.currentThread().getName() + "卖完第"
                                + ticket + "张票");
                        System.out.println("顾客从"
                                + Thread.currentThread().getName() + "买到第"
                                + ticket + "张票");
                        --ticket;
                    } catch (InterruptedException e) {
                        System.out.println("卖票不成功");
                        System.exit(1);
                    }
                } else {
                    break;
                }
            }
        }
    }
    恩,还没试,但是逻辑上应该正确,,但是你在if里加了个--,下面的--ticket就可以去掉了。
    你还是太粗心,O(∩_∩)O哈哈~
      

  8.   

    楼主一开始的两个程序,都是多线程去抢ticket,不上锁肯定会冲突的,楼上说得对,第二个没有出现负数是因为时间太短而已!  
    试想这么一个场景: 到最后一张票的时候,4个线程同时检查“ticket > 0”进去了,进去了就会卖出来,可是只有一张票,所以出现负数。
    所以此处重点在于同步好这些ticket。而且考虑到性能问题,把锁的范围缩得越小越好。楼主这里只要加个控制变量 ticketControl 就可以很好解决线程冲突的问题,而且能使效率最大化。class Ticket extends Thread {
     
        private volatile int ticket = 5;
        private volatile int ticketControl = ticket;
     
        @Override
        public void run() {
            while (true) {
                if (ticketControl-- > 0) {
                    System.out.println("顾客到达 "
                            + Thread.currentThread().getName() + "售票台");
                    System.out.println("售票台" + Thread.currentThread().getName()
                            + "准备出售第" + ticket + "张票");
                    try {// 具体卖票过程
                        System.out.println("售票台需要5分钟出售这张票");
                        for (int i = 1; i < 5; i++) {
                            Thread.sleep(100);
                            System.out.println(i + "分钟");
                        }
                        System.out.println("售票台"
                                + Thread.currentThread().getName() + "卖完第"
                                + ticket + "张票");
                        System.out.println("顾客从"
                                + Thread.currentThread().getName() + "买到第"
                                + ticket + "张票");
                        --ticket;
                    } catch (InterruptedException e) {
                        System.out.println("卖票不成功");
                        System.exit(1);
                    }
                } else {
                    break;
                }
            }
        }
    }
    恩,还没试,但是逻辑上应该正确,,但是你在if里加了个--,下面的--ticket就可以去掉了。
    你还是太粗心,O(∩_∩)O哈哈~
    我用了两个参数呢,两个是不同的!你跑一下就知道了,如果只用一个的话,会冲突,出现负数的票数。用两个就不会了!所以--ticket是要的