4.1 设计线程安全的类
三要素:
- 找出构成对象状态的所有变量
- 找出约束状态变量的不变性条件
- 建立对象状态的并发访问管理策略
4.1.1 收集同步需求
状态空间:对象与变量的所有可能取值。状态空间越小,越容易判断线程的状态。final类型的域使用得越多,就越能建华对象可能状态的分析过程。
4.1.2 依赖状态的操作
类的不变性条件与后验条件约束了在对象上有哪些状态和状态转换是有效的。
4.1.3 状态的所有权
4.2 实例封闭
将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁。
封闭机制更易于构造线程安全的类,因为当封闭类的状态时,在分析类的线程安全性时就无须检查整个程序。
4.2.1 监视器模式
把对象的所有可变状态都封装起来,并由对象自己的内置锁来保护。
4.3 线程安全性的委托
如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态转换,那么可以将线程安全性委托给底层的状态变量。
如果一个状态变量是线程安全的,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量。
4.4 在现有的线程安全类中添加功能
例如:给安全list添加putIfAbsent方法
1、直接extend扩展源码会改变同步策略
public class BetterVector extends Vector {
public synchronized boolean putIfAbsent(E x) {
}
}
2、客户端加锁同样会破坏同步策略的封装性
public class ListHelper {
public List list = Collections.synchronizedList(new ArrayList());
public boolean putIfAbsent(E x) {
synchronized (list) {
}
}
}
3、组合
public class ImprovedList implements List {
private final List list;
public ImprovedList(List list) {
this.list = list;
}
public synchronized boolean putIfAbsent(T x) {
}
@Override
public synchronized void clear() {
list.clear();
}
}
ImprovedList通过自身的内置锁增加了一层额外的加锁,可能导致性能损失,但是更健壮。这也是Java监视器模式。