卖票案例出现了线性安全问题:卖出了不存在的票和重复的票。
解决线性安全的第一种方案:使用同步代码块。
格式:
synchronized(锁对象){
可能出现线性安全问题的代码(访问了共享数据的代码)
}
注意:
- 同步代码块中的锁对象,可以使用任意的对象
- 但是必须保证多个线程使用的锁对象是同一个
- 锁对象作用
把同步代码块锁住,只让一个线程在同步代码块中执行
案例:
定义一个Runnable接口的实现类:
package XianCheng.MaiPiaoSynchronized;
/*
卖票案例出现了线性安全问题:卖出了不存在的票和重复的票。
解决线性安全的第一种方案:使用同步代码块。
格式:
synchronized(锁对象){
可能出现线性安全问题的代码(访问了共享数据的代码)
}
注意:
1. 同步代码块中的锁对象,可以使用任意的对象
2. 但是必须保证多个线程使用的锁对象是同一个
3. 锁对象作用:
把同步代码块锁住,只让一个线程在同步代码块中执行
*/
public class RunnableImpl implements Runnable{
//定义一个多线程共享的票源
private int ticket = 35;
//创建一个锁对象
Object obj = new Object();
//设置线性任务:卖票
@Override
public void run() {
//使用死循环,让卖票操作重复执行
while(true){
//同步代码块
synchronized (obj){
//先判断票是否存在
if(ticket > 0){
//提高安全问题出现的概率,让程序睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//票存在,卖票 ticket...
System.out.println(Thread.currentThread().getName() + " --> 正在卖第" + ticket + "张票");
ticket--;
}
}
}
}
}
使用实现类:
package XianCheng.MaiPiaoSynchronized;
/*
模拟卖票案例
创建3个线程,同时开启,对共享的票进行出售
*/
public class Demo01Ticket {
public static void main(String[] args) {
//创建Runnable接口的实现类对象
RunnableImpl run = new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现类对象
Thread t0 = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
//调用start方法开启多线程
t0.start();
t1.start();
t2.start();
}
}
运行结果:
Thread-0 --> 正在卖第60张票
Thread-0 --> 正在卖第59张票
Thread-0 --> 正在卖第58张票
Thread-0 --> 正在卖第57张票
Thread-0 --> 正在卖第56张票
Thread-0 --> 正在卖第55张票
Thread-0 --> 正在卖第54张票
Thread-0 --> 正在卖第53张票
Thread-0 --> 正在卖第52张票