同步与互斥经典案例——模拟火车票售票系统

来源:互联网 发布:linux解压缩命令gz 编辑:程序博客网 时间:2024/05/19 00:09

案例描述:模拟火车站多个售票窗口同时售票(总共20张票,5个窗口同时卖票)

案例代码如下:

/** * 售票类--票的唯一来源 * @author Administrator */class TicketSys {private int totalTickets = 20; // 总票数private int saledTickets = 0; // 已经售票数目// 添加同步后,同一时间只能有一个窗口卖票public synchronized void saleTicket() {if (totalTickets <= 0) {throw new RuntimeException("票已经卖完");}// 卖掉一张票saledTickets++;System.out.println("打印一张票!已经售出" + saledTickets);try {Thread.sleep(20);  //模拟卖一张票的过程需要花20毫秒} catch (InterruptedException e) {e.printStackTrace();}// 总票数 -1totalTickets--;System.out.println("剩余票数:" + totalTickets);}}
======================================

/** * 售票窗口类 * @author Administrator */class SaleTicket implements Runnable {private TicketSys ticketSys;public SaleTicket(TicketSys ticketSys) {this.ticketSys = ticketSys;}@Overridepublic void run() {while (true) {try {ticketSys.saleTicket();} catch (RuntimeException e) {break;}}}}
================================

/** * 启动类 * @author Administrator */public class SaleTicketSystem {public static void main(String[] args) {TicketSys system = new TicketSys();// 票源唯一for (int i = 0; i < 5; i++) {// 模拟5个窗口同时卖票SaleTicket saleTicket = new SaleTicket(system);new Thread(saleTicket).start();}}}
=======================================
如果售票类中的售票方法没有添加同步synchronized关键字,那么运行结果如下所示:

打印一张票!已经售出1打印一张票!已经售出2打印一张票!已经售出3打印一张票!已经售出4打印一张票!已经售出5剩余票数:19剩余票数:19打印一张票!已经售出6打印一张票!已经售出7剩余票数:18......剩余票数:7打印一张票!已经售出20剩余票数:6打印一张票!已经售出21剩余票数:6打印一张票!已经售出22剩余票数:5打印一张票!已经售出23剩余票数:4打印一张票!已经售出24剩余票数:3打印一张票!已经售出25剩余票数:2打印一张票!已经售出26剩余票数:1打印一张票!已经售出27剩余票数:0剩余票数:-1剩余票数:-2剩余票数:-3剩余票数:-4
看看,售票过程完全错误,你能明白是为什么吗?

如果添加了同步synchronized关键字,那么运行结果如下所示:

打印一张票!已经售出1剩余票数:19打印一张票!已经售出2剩余票数:18......打印一张票!已经售出11剩余票数:9打印一张票!已经售出12剩余票数:8打印一张票!已经售出13剩余票数:7打印一张票!已经售出14剩余票数:6打印一张票!已经售出15剩余票数:5打印一张票!已经售出16剩余票数:4打印一张票!已经售出17剩余票数:3打印一张票!已经售出18剩余票数:2打印一张票!已经售出19剩余票数:1打印一张票!已经售出20剩余票数:0