在这个程序中我们一共售卖1-100号票,一共有4个窗口,首先我们看程序如下
package com.study.article1;
/**
* @func 多线程实现窗口卖票.
* @author 张俊强~
* @time 2017/10/27 12:52
* */
class Ticket implements Runnable {
private int ticket = 1000;
public void salesTickets() {
synchronized (this) { //加同步锁
if (ticket > 0) { //再次判断是否还有余票
System.out.println(Thread.currentThread().getName() + "正在卖第[ " + ticket-- + " ]张票...");
}
}
}
public void run() {
while (ticket > 0) { //当还有余票的时候继续卖票
salesTickets(); //调用卖票方法
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class TicketDemo {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread w1 = new Thread(t,"窗口一");// 创建四个窗口
Thread w2 = new Thread(t,"窗口二");
Thread w3 = new Thread(t,"窗口三");
Thread w4 = new Thread(t,"窗口四");
w1.start();
w2.start();
w3.start();
w4.start();
}
}
针对以上的程序做一下两点说明
(1).为什么要加同步锁synchronized (this)
?
如果不加同步锁的话会出现这样子的情况(只举一个例子)
public void salesTickets() {
//synchronized (this) { //加同步锁
//if (ticket > 0) {
// 这里标志位 【位置一】
System.out.println(Thread.currentThread().getName() + "正在卖第[ " + ticket-- + " ]张票...");//【卖票操作】
// 这里标志位 【位置二】
//}
//}
}
当票库中只有一张票的时候,一号线程走到了【位置一】
再他刚准备执行【卖票操作】的时候,二号线程走到了【位置一】(没有加锁就可以进来)
这时候一号线程卖完了票ticket=0
,二号线程就把第零张票给卖出去了
(2).为什么要两次判断是否还有余票?
有的同学就会有疑问,我加一个同步锁就是啦,为什么还要两次判断是否还有余票呢?
public void run() {
while (ticket > 0) { //当还有余票的时候继续卖票
// 这里标志为 【位置一】
salesTickets(); //调用卖票方法
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
当票库中只有一张票的时候,一号线程走到了【位置一】
再他刚准备执行【调用卖票方法】的时候,二号,三号线程都走到了【位置一】
在后面同步方法里面又没有做是否还有余票的判断,就会把o号
和-1号
也给卖了。
设想,这样子如果是在12306,岂不是很混乱,一群人拿着0号,-1号,-2号……
车票一脸懵逼的上了车……