如何通过线程安全的组件组合设计线程安全的类?
首先要封装所有状态,封装简化了安全类的实现过程。
设计线程安全的类,需考虑三个基本要素

  • 找出构成对象状态的所有变量
  • 找出约束状态变量的约束条件–>不变性条件和后验条件
  • 建立对象状态的并发访问管理策略

要满足对象的状态的约束条件,就需要借助于原子性和封装性。

依赖状态的操作
如果某个操作中包含有基于状态的先验条件(Precondition),如没有则添加,那么这个操作称为依赖状态操作 。

实现等待条件为真才执行的操作的方法有:
内置机制(如等待和通知);现有的类库中的类(如BlockingQueue)。

状态的所有权
对象封装了它拥有的状态,则对象对它封装的状态拥有所有权。
如果发布一个可变对象的引用,就不在独占所有权。
容器类表现为所有权分离,容器类拥有自身的状态,而客户代码则拥有容器内各个对象的状态。

通过封闭和加锁实现线程安全的类

public class PersonSet {
    private final Set<Person> mySet = new HashSet<Person>();

    public synchronized void addPerson(Person p) {
        mySet.add(p);
    }

    public synchronized boolean containsPerson(Person p) {
        return mySet.contains(p);
    }

    interface Person {
    }
}

PersonSet类是线程安全的类,它将状态(mySet )封装起来,并对访问这个状态的方法进行加锁。
但Person类如果是可变的,需要设计成线程安全的类来安全的使用Person对象。

创建线程安全类的策略1 - Java监视器模式
Java监视器模式的对象会把对象的所有可变状态都封装起来,并有对象自己的内置锁来保护。

私有锁

public class PrivateLock {
    private final Object myLock = new Object();
    Widget widget;
    void someMethod() {
        synchronized (myLock) {
            // Access or modify the state of widget
        }
    }
}

创建线程安全类的策略2 - 线程安全性的委托
通过对象的组合,将线程安全性委托给现有的线程安全类。
如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作中都不包含无效状态的转换,那么可以将线程安全性委托给底层的状态变量。
示例:PersonList将线程安全性委托给底层的线程安全状态变量

public class PersonList {
    private final List<Person> myList = new CopyOnWriteArrayList<Person>();//安全性委托

    public void addPerson(Person p) {
        myList.add(p);
    }

    public boolean containsPerson(Person p) {
        return myList.contains(p);
    }

    interface Person {
    }
}

线程安全性委托要考虑下列问题:
1. 状态变量要是线程安全的。
2. 多个线程安全的状态变量是独立的。
3. 多个线程安全的状态变量有不变性条件约束–不能直接委托,需要对操作加锁。
4. 类含有复合操作– 不能直接委托,需要对操作加锁。
5. 什么条件下可以发布底层的状态变量?
如果一个状态变量是线程安全的,并且没有任何不变性条件约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量。

在现有的线程安全类中添加功能
1.修改原始的类
2.扩展原始类(继承)
3.扩展原始类的功能,将扩展代码放到一个“辅助类”中–通过客户端加锁。
4.组合–通过客户端加锁。

示例: 扩展原始类的功能

@NotThreadSafe
class BadListHelper <E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    public synchronized boolean putIfAbsent(E x) {//和list对象不是同一锁
        boolean absent = !list.contains(x);
        if (absent)
            list.add(x);
        return absent;
    }
}

@ThreadSafe
class GoodListHelper <E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public boolean putIfAbsent(E x) {
        synchronized (list) {//和list对象是同一个锁
            boolean absent = !list.contains(x);
            if (absent)
                list.add(x);
            return absent;
        }
    }
}

示例: 组合

@ThreadSafe
public class ImprovedList<T> implements List<T> {
    private final List<T> list;

    /**
     * PRE: list argument is thread-safe.
     */
    public ImprovedList(List<T> list) { this.list = list; }

    public synchronized boolean putIfAbsent(T x) {
        boolean contains = list.contains(x);
        if (contains)
            list.add(x);
        return !contains;
    }

    // Plain vanilla delegation for List methods.
    // Mutative methods must be synchronized to ensure atomicity of putIfAbsent.

    public int size() {
        return list.size();
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public boolean contains(Object o) {
        return list.contains(o);
    }

    public Iterator<T> iterator() {
        return list.iterator();
    }

    public Object[] toArray() {
        return list.toArray();
    }

    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    public synchronized boolean add(T e) {
        return list.add(e);
    }

    public synchronized boolean remove(Object o) {
        return list.remove(o);
    }

    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    public synchronized boolean addAll(Collection<? extends T> c) {
        return list.addAll(c);
    }

    public synchronized boolean addAll(int index, Collection<? extends T> c) {
        return list.addAll(index, c);
    }

    public synchronized boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    public synchronized boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    public boolean equals(Object o) {
        return list.equals(o);
    }

    public int hashCode() {
        return list.hashCode();
    }

    public T get(int index) {
        return list.get(index);
    }

    public T set(int index, T element) {
        return list.set(index, element);
    }

    public void add(int index, T element) {
        list.add(index, element);
    }

    public T remove(int index) {
        return list.remove(index);
    }

    public int indexOf(Object o) {
        return list.indexOf(o);
    }

    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }

    public ListIterator<T> listIterator() {
        return list.listIterator();
    }

    public ListIterator<T> listIterator(int index) {
        return list.listIterator(index);
    }

    public List<T> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }

    public synchronized void clear() { list.clear(); }
}