第四章 对象的组合
4.1 设计线程安全的类
设计线程安全类的三个基本要素:
1. 找出构成对象状态的所有变量2. 找出约束状态变量的不变性条件
3. 建立对象状态的并发访问管理策略
4.2 实例封闭
通过将封闭机制与合适的加锁策略结合起来,可以确保以线程安全的方式来使用非线程安全的对象。
例如:
public class PersonSet{
private final Set<Person> mySet = new HashSet<Person>();
public sychronized void addPersion(Person p) {
mySet.add(p)
}
public sychronized boolean containsPerson(Person p) {
return mySet.contains(p);
}
}
mySet封闭在类中,且只有两个加锁的方法可以访问。
4.3 线程安全性的委托
当只有一个状态进行委托,必然是线程安全的,而多个状态并且状态间存在依赖关系时,就很可能存在线程安全问题。
class NumberRange {
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int i){
//不安全的 先检查后执行
if(i > upper.get()){
throw new RuntimeException("最小值不能比最大值大");
}
lower.set(i);
}
public void setUpper(int i){
//不安全的 先检查后执行
if(i < lower.get()){
throw new RuntimeException("最大值不能比最小值小");
}
upper.set(i);
}
}
例如上面的类,lower和upper都委托给AtomicInteger,本身分别是线程安全的,但存在lower不能大于upper这个限制条件,组合起来就不是线程安全的。