▶ 线程安全问题的产生
编辑
产生安全问题的前提:只有当多个线程访问了共享的数据时才有可能产生线程安全问题
代码实现上面卖票过程:
编辑
编辑
想要提高安全问题出现的概率,让程序睡眠:
编辑
编辑
▶ 解决线程安全问题 ----- 线程同步
当使用多个线程访问同一资源,且多个线程中对资源有写的操作,就容易出现线程安全问题。
要解决上述多线程并发访问一个资源的安全问题,java中提供了同步机制(Synchronized)来解决。
有三种方式完成同步操作:
1. 同步代码块
格式: synchronized( 锁对象 ) {
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注意: (1)同步代码块中的锁对象可以使用任意的对象
(2)但是必须保证多个线程使用的锁对象是同一个
(3)锁对象的作用:把同步代码块锁住,只让一个线程在同步代码块中执行
编辑
2. 同步方法
格式:就是定义方法的格式,只不过要加上关键字 synchronized
修饰符 synchronized 返回值类型 方法名( 参数列表 ){
可能会出现线程安全问题的代码( 访问了共享数据的代码 )
}
使用步骤:(1)把访问了共享数据的代码抽取出来,放到一个方法中
(2)在方法上添加 synchronized 修饰符
定义一个同步方法,同步方法也会把方法内部的代码锁住,只让一个线程执行。
同步方法的锁对象是谁?就是实现类对象 new RunnableImpl(),也就是 this 。
静态同步方法: 就是在同步方法的基础上加上关键字 “ static ”
静态同步方法的锁对象是谁? 不能是 this ,this 是创建对象后产生的,静态方法优于对象,静态方法的锁对象是本类的class属性 ---> class文件对象(反射)
3. 锁机制
java.util.concurrent.locks.Lock接口
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作
Lock接口中的方法: void lock() --- 可获取锁
void unlock() --- 释放锁
java.util.concurrent.locks.ReentrantLock implements Lock接口
使用步骤:(1)在成员位置创建一个 ReentrantLock 对象
(2)在可能会出现安全问题的代码前调用 Lock 接口中的方法 lock 获取锁
(3)在可能会出现安全问题的代码后调用 Lock 接口中的方法 unlock 释放锁