第四章 对象的组合
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这个限制条件,组合起来就不是线程安全的。