关于线程问题的探讨(售票问题)
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输出。