Java并发编程实战(二)-线程安全性
要编写线程安全的代码,核心在于要对状态访问操作进行管理,特别是共享的(shared)和可变的(mutable)状态的访问。
对象的状态是指存储在状态变量中的数据,可能包括依赖对象的域。
“共享”意味着变量可以由多个线程同时访问;“可变”意味着变量的值在其生命周期内可以发生变化。
一个对象是否需要是线程安全的,取决于它是否被多个线程访问,而不是对象要实现的功能。
修改线程不安全代码的方法:
1.不再线程间共享该变量的状态(封闭线程)
2.将状态变量修改为不可变的
3.在访问变量状态时使用同步
在设计代码的初期就应该考虑线程安全的问题
2.1什么是线程安全性
无状态变量一定是线程安全的
2.2原子性
2.2.1竞态条件
由于不恰当的执行时序而出现不正确的结果,也即当某个计算的正确性取决于多个线程交替执行的时序时,那么就会发生竞态条件
2.2.2示例:延迟初始化中的竞态条件
2.2.3复合操作
“先检查后执行”和“读取-修改-写入”等操作统称为符合操作:包含了一组必须以原子方式执行的操作以确保线程安全性
在实际的情况中,应尽可能的使用先用现有的线程安全的对象来管理状态。
2.3加锁机制
当不变性的条件中涉及多个变量时,各个变量之间不是彼此独立的,当一个变量更新,需要在同一个原子操作中对其他变量同时进行更新
2.3.1内置锁
使用同步代码块的锁就是方法调用所在的对象,静态的synchronized方法以Class对象作为锁
2.3.2重入
锁传递,不会由于锁竞争产生死锁
2.4用锁来保护状态
对于可能被多个线程同时访问的可变状态变量,在访问它时都需要持有同一个锁,在这种情况下,我们称状态变量是由这个锁保护的
2.5活跃性与性能
锁将降低代码的性能,所以需要在简单性和性能之间寻找一个最佳的平衡

浙公网安备 33010602011771号