对象的组合《java并发编程实战》
概述
到目前为止,我们已经介绍了关于线程安全与同步的一些基础知识,然而,我们不希望对每一次内存访问都进行分析以确定程序是线程安全的,而是希望将一些现有的线程安全组件组合为更大规模的组件或程序。
设计线程安全的类
package chapter4; import common.GuardedBy; import common.ThreadSafe; /** * @author zhen * @Date 2018/10/26 11:39 */ @ThreadSafe public final class Counter { @GuardedBy("this") private long value = 0; public synchronized long getValue() { return value; } public synchronized long increment() { if (value == Long.MAX_VALUE) { throw new IllegalStateException("counter overflow"); } return ++value; } }
通过使用封装技术,可以使得在不对整个程序进行分析的情况下就可以判断一个类是否是线程安全的。
在设计线程安全类的过程中,需要包含以下三个基本要素:
找出构成对象状态的所有变量;
找出约束状态变量的不可变条件;
建立对象状态的并发访问管理策略
1>收集同步需求
如果不了解对象的不变性条件和后验条件,那么就不能确保线程安全性。要满足在状态变量的有效值或状态转换上的各种约束条件,需要借助原子性和封装性
2>依赖状态的操作
类的不变性条件与后验条件约束了再对象上有哪些状态和状态转换是有效的。在某些对象的方法中还包含一些基于状态的先验条件。
在java中,等待某个条件为真的各种内置机制(包括等待和通知机制)都与内置加锁机制紧密关联,要正确使用它们并不容易。想要实现某个等待先验条件为真时才执行的操作,一种更简单的方法是通过现有库中的类(例如阻塞队列Blocking Queue或者信号量Semaphore)来实现依赖状态的行为。
3>状态的所有权
垃圾回收机制使得避免了如何处理所有权的问题
对象封装它拥有的状态反之,对它封装的状态拥有所有权。如果发布了某个可变对象的引用,共享控制权。容器类通常表现出所有权分离的形式。
实例封闭
将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容易确保线程在访问数据时总能持有正确的锁
封闭机制更易与构造线程安全的类,因为当封闭类的状态时,在分析类的线程安全性检查时就无须检查整个程序
@ThreadSafe public class PersonSet { @GuardedBy("this") private final Set<Person> mySet = new HashSet<>(); public synchronized void addPerson(Person p) { mySet.add(p); } public synchronized boolean containsPerson(Person p) { return mySet.contains(p); } }
1>线程监视器模式:
遵循java监视器模式的对象会把对象的所有可变状态都封装起来,并由对象自己的内置锁来保护
public class PrivateLock { private final Object myLock = new Object(); @GuardedBy("myLock") Widget widget; void someMethod() { synchronized (myLock) { //访问或者修改Widget的状态 } } }
线程安全性的委托
如果一个类是由多个独立且线程安全的状态变量组成,并且在所有的操作都不包含无效状态转换,那么可以将线程安全性委托给底层的状态变量
如果一个状态变量是线程安全的,并且没有任何不变性条件来约束它的值,在变量的操作上也不存在任何不允许的状态转换,那么就可以安全地发布这个变量
在现有的线程安全类中添加功能
修改原始类
拓展这个类
将拓展代码放入一个辅助类中
1、客户端加锁机制
2、组合
/** * @author zhen * @Date 2018/10/31 15:08 * 拓展Vector并增加一个若没有则添加方法 */ @ThreadSafe public class BetterVector<E> extends Vector<E> { public synchronized boolean putIfAbsent(E x) { boolean absent = !contains(x); if (absent) { add(x); } return absent; } }
/** * @author zhen * @Date 2018/10/31 15:24 * 非线程安全的“若没有则添加” */ @NotThreadSafe public class ListHelper<E> { public List<E> list = Collections.synchronizedList(new ArrayList<E>()); //这里的锁时ListHelper对象,虽然list使用synchronized保证同步,但是锁不一样 public synchronized boolean putIfAbsent(E x) { boolean absent = !list.contains(x); if (absent) { list.add(x); } return absent; } }
/** * @author zhen * @Date 2018/10/31 15:32 * 通过客户端加锁来实现“若没有则添加” */ @ThreadSafe public class ListHelper1<E> { public List<E> list = Collections.synchronizedList(new ArrayList<E>()); public boolean putIfAbsent(E x) { synchronized (list) { boolean absent = !list.contains(x); if (absent) { list.add(x); } return absent; } } }
/** * @author zhen * @Date 2018/10/31 15:40 * 通过组合实现若没有则添加 */ @ThreadSafe public class ImprovedList<T> implements List<T> { private final List<T> list; 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; } @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public Iterator<T> iterator() { return list.iterator(); } @Override public Object[] toArray() { return list.toArray(); } @Override public <T1> T1[] toArray(T1[] a) { return list.toArray(a); } @Override public boolean add(T t) { return list.add(t); } @Override public boolean remove(Object o) { return list.remove(o); } @Override public boolean containsAll(Collection<?> c) { return list.containsAll(c); } @Override public boolean addAll(Collection<? extends T> c) { return list.addAll(c); } @Override public boolean addAll(int index, Collection<? extends T> c) { return list.addAll(index, c); } @Override public boolean removeAll(Collection<?> c) { return list.removeAll(c); } @Override public boolean retainAll(Collection<?> c) { return list.retainAll(c); } @Override public void clear() { list.clear(); } @Override public T get(int index) { return list.get(index); } @Override public T set(int index, T element) { return list.set(index, element); } @Override public void add(int index, T element) { list.add(index, element); } @Override public T remove(int index) { return list.remove(index); } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @Override public ListIterator<T> listIterator() { return list.listIterator(); } @Override public ListIterator<T> listIterator(int index) { return list.listIterator(index); } @Override public List<T> subList(int fromIndex, int toIndex) { return list.subList(fromIndex,toIndex); } }
将同步策略文档化
在文档中说明客户代码需要了解的线程安全保证以及代码维护人员需要了解的同步策略。

浙公网安备 33010602011771号