关于线程问题的探讨(售票问题)

package SellTickets;

public class SellTickets01 implements Runnable{

    private static int ticketNum = 100;

    @Override
    public void run() {
        while(true)
        {
            if(ticketNum<=0)
            {
                System.out.println("售票结束...");
                break;
            }
            try{
                Thread.sleep(50);
            }catch (Exception e)
            {
                throw new RuntimeException(e);
            }
            
            System.out.println("窗口"+Thread.currentThread().getName()+"剩余票数:"+(--ticketNum));
        }
    }

    public static void main(String[] args) {
        SellTickets01 sellTickets01 = new SellTickets01();
        SellTickets01 sellTickets02 = new SellTickets01();
        SellTickets01 sellTickets03 = new SellTickets01();
        Thread thread01 = new Thread(sellTickets01);
        Thread thread02 = new Thread(sellTickets02);
        Thread thread03 = new Thread(sellTickets03);
        thread01.start();
        thread02.start();
        thread03.start();
    }
}    

首先这是韩顺平老师的售票代码,老师发现了超售的问题(剩余票数小于0了,截图如下)

 那么面对这样的问题我们该怎么解决呢?

我是这样分析的,首先这段代码有一段50毫秒的休眠Thread.sleep(50),那么在这一线程休眠的时候,其他没有休眠的线程肯定会运行。那么好了,此时假设我们的01线程已经进入了休眠,那它必定已经走过了if(ticketNum<=0)语句,休眠结束以后它必定会执行System.out.println("窗口"+Thread.currentThread().getName()+"剩余票数:"+(--ticketNum));语句,那么也就意味着票数必定会减一。那么好,如果01线程进入休眠前if语句判断的ticketNum正好等于1,按我们的思维逻辑票肯定不能再卖了,但是其他的线程并不这么认为,因为在01线程休眠时,假设02线程执行if(ticketNum<=0)语句,而此时ticketNum还是等于1,所以它也不会跳出while循环,并将继续执行下面的语句,进入休眠,休眠结束以后执行System.out.println("窗口"+Thread.currentThread().getName()+"剩余票数:"+(--ticketNum));语句,那么我们的ticketNum就执行两次减一,票数变成-1,不符合实际情况。

我描述的有点繁琐,但是基本意思我想已经表达清楚了。改进方法也很简单,因为我们的if语句在线程休眠之前才导致了问题的产生,那么把if语句放在程序休眠之后就不会出现类似的问题了。

 我试了好几次都是这个结果,所以我想大概率问题解决了,如果有什么考虑欠缺的地方,非常欢迎给位大佬为我提出来,谢谢!

另外还有一个方法,只要让--ticketNum这个语句提前,执行完if语句后立马令ticketNum减一,那么线程就可以放心的休眠了。

 只是想了好久,弄不明白为什么会有这么多剩余票为0输出。

posted @ 2023-07-14 22:41  那啥cjj  阅读(12)  评论(0编辑  收藏  举报