线程安全问题
- 线程安全问题出现的原因
- 案例实战
1. 线程安全出现的原因
这里我们让多个线程共享同一个卖票资源:
public class RunnableImpl implements Runnable {
//总的票得数量
int tickets = 20;
@Override
public void run() {
while (true) {
if (tickets > 0) {
//为系统性能考虑,每个线程稍微休息一下
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "的第" + tickets + "张票");
tickets--;
}
}
}
}
public class DemoThreadSafe {
public static void main(String[] args) {
//创建Runnable接口的实现类对象
RunnableImpl run = new RunnableImpl();
//创建多个Thread类对象
Thread r0 = new Thread(run);
Thread r1 = new Thread(run);
Thread r2 = new Thread(run);
//用start方法开启线程
r0.start();
r1.start();
r2.start();
}
}
输出:
Thread-1的第20张票
Thread-2的第20张票
Thread-0的第20张票
Thread-2的第17张票
Thread-0的第16张票
Thread-1的第16张票
Thread-2的第14张票
Thread-0的第13张票
Thread-1的第12张票
Thread-2的第11张票
Thread-0的第11张票
Thread-1的第11张票
Thread-0的第8张票
Thread-2的第8张票
Thread-1的第6张票
Thread-2的第5张票
Thread-0的第4张票
Thread-1的第3张票
Thread-2的第2张票
Thread-0的第2张票
Thread-1的第0张票
Thread-2的第-1张票
从上面的例子可以看到, 有被重复卖出去的票,还有第-1,0张票,出现了线程安全问题。因为线程卖出了重复的票和不存在的票。
出现这个问题的原因是,我们创建的每个线程执行到sleep()语句之后就放弃了cpu的使用权。等到它睡醒之后,它照样还是会往下执行, 不会管其它票的数量已经减少了。