一、线程安全
如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
1.1、线程安全演示
电影院要卖票,我们模拟电影院的卖票过程。假设要播放的电影是 “火影忍者”,本次电影的座位共100个(本场电影只能卖100张票)。
我们来模拟电影院的售票窗口,实现多个窗口同时卖 “火影忍者”这场电影票(多个窗口一起卖这100张票)需要窗口,采用线程对象来模拟;票使用Runnable接口子类来模拟。
测试类:
public class ThreadDemo {
public static void main(String[] args) {
//创建票对象
Ticket ticket = new Ticket();
//创建3个窗口
Thread t1 = new Thread(ticket, "买票窗口1");
Thread t2 = new Thread(ticket, "买票窗口2");
Thread t3 = new Thread(ticket, "买票窗口3");
t1.start();
t2.start();
t3.start();
}
}
模拟票:
public class Ticket implements Runnable {
//共100票
int ticketCount = 100;
@Override
public void run() {
//模拟卖票
while(true){
if (ticket > 0) {
//模拟选坐的操作
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticketCount--);
}
}
}
}
运行结果发现出现问题票数为-1:
买票窗口1正在卖票:100
买票窗口2正在卖票:99
买票窗口3正在卖票:98
买票窗口1正在卖票:97
……
买票窗口3正在卖票:6
买票窗口1正在卖票:5
买票窗口3正在卖票:4
买票窗口1正在卖票:2
买票窗口2正在卖票:3
买票窗口1正在卖票:1
买票窗口3正在卖票:0
买票窗口2正在卖票:-1
其实,线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
我们从内存角度来分析一下:
票只剩下一张的时候:
解决办法:当一个线程进行数据操作的时候,无论是否休眠,其他线程都只能等待。