一、案例:模拟火车站售票,开启三个窗口售票
- 出现的问题:卖票过程中,出现了重票、错票 ==>也就是出现了线程的安全问题
- 问题出现的原因:当某个线程操作车票的过程中,尚未操作完成时,其他线程参与进来,也操作车票。
- 解决思路:当一个线程(一个窗口)在操作ticket(火车票)的时候,其他线程不能参与进来。直到这个线程(这个窗口)操作完ticket(火车票)时,其他线程才可以开始操作ticket(火车票)。这种情况即使这个线程(这个窗口)出现了阻塞,也不能被改变。
- 解决办法:在Java中,我们通过同步机制,来解决线程的安全问题。
方式一:同步代码块
方式二:同步方法
方式三:Lock锁(JDK5.0新增) - 同步的方式:
好处:解决了线程的安全问题。
局限性:操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。
例如下方代码就会出现重票、漏票的情况
class Window implements Runnable{
// 定义共有100张票
private int ticket = 100;
Object obj = new Object();
@Override
public void run() {
while(true){
// 如果还有票,就售票
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
ticket --;
} else {
break;
}
}
}
}
public class WindowTest {
public static void main(String[] args) {
// 创建售票窗口对象
Window window = new Window();
// 创建Thread对象
Thread t1 = new Thread(window );
Thread t2 = new Thread(window );
Thread t3 = new Thread(window );
// 给线程设置线程名称
t1.setName("窗口1")