Java并发编程实战

来源:互联网 发布:大型系统网络拓扑图 编辑:程序博客网 时间:2024/05/01 06:15

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

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

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

依赖状态的操作
如果某个操作中包含有基于状态的先验条件(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.组合–通过客户端加锁。

示例: 扩展原始类的功能

@NotThreadSafeclass 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;    }}@ThreadSafeclass 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;        }    }}

示例: 组合

@ThreadSafepublic 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(); }}
0 0