线程同步-订票系统初步分析
订票系统差不多是我们最熟悉的一个关于线程并发的问题,如何做到多个售票窗口同时售票而不会导致将同一张票卖给多个旅客,首先很直观 的一点就是当我们把售票余量的增减弄成一个事务,如此一来在增减票余量的代码执行的时候只能允许一个线程操作也就是出票只能是总部出票,那么一个简易的模型就出来了。
首先所有车票(虚拟票使用票号代替)都存放在总部,在总部只需完成接收售票点的出票请求来完成增减票余量并产生唯一票号分发给售票点,然后各售票点将票卖给旅客(所以这个模型的通俗的理解就是各个售票点代替旅客去售票总部排队申请出票,这样就不会出现同一张票卖给多个旅客),这也就是同步与互斥的一个案例吧。
这里讲解一个使用Java实现这个案例的代码吧
很明显这里各个售票点销售的都是售票总部的票余量,所以各个售票点需要共享票余量这个变量。因而我们可以创建一个售票窗口类
class TicketsWindows implements Runnable{ private int ticketsNums = 2000; public void run(){ while(true){ //同步代码块,相当于一个事务,相当于售票总部完成的工作 synchronized(this){ //判断票余量 if(ticketsNums>0){ System.out.println(Thread.currentThread().getName() + "正在销售第" + (2000-ticketsNums+1) + "张票"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } ticketsNums--; }else{ System.out.println("票已售罄,请购买其他时间的票!!!"); break; } } } } }
然后我们在主类里面创建一个售票窗口对象,多个线程对象来共享这个售票窗口对象来模拟多个售票代售点
public class MainActivity { public static void main(String []args){ TicketsWindows tw1 = new TicketsWindows(); Thread t1 = new Thread(tw1); Thread t2 = new Thread(tw1); Thread t3 = new Thread(tw1); t1.start(); t2.start(); t3.start(); } }
这里我们创建一个售票窗口对象作为售票总部,里面的同步块就是各代售点向售票总部提出出票申请后售票总部完成票余量增减产生票号出票的操作,中间使用synchronized关键字来定义一个同步块,this表示当前同步块。我在售票窗口类中增减票余量后使用线程休眠来体现可能出现的同时多个线程来订票,如此更能体现出多线程同步互斥的现象。
总结:其实从多线程以及之前学习操作系统时的同步互斥问题和并发并行,这里我想说一点就是所谓的并发如果按我个人的理解这只是一个宏观的问题,在微观上还是有先后顺序的,也就是说当只有一个cpu或者1核其实际上在同一时刻只可能会处理一个问题,也就是说我们在理解这些同步互斥并发的时候都是基于使用一定的算法来完成将一件事情分成多个更小的事情来与其他事情分解成的小事情交替完成从而达到并发的目的。