在设计线程安全类的过程当中,须要包含如下三个基本要素: 1. 找出构成对象状态的全部变量 2. 找出约束状态变量的不变性条件 3. 创建对象状态的并发访问管理策略
遵循Java监视器模式的对象会把对象的全部可变状态都封装起来,并由对象本身的内置锁来保护 如下代码是对象使用私有锁的例子:安全
public class PrivateLock { private final Object myLock = new Object(); public void doSomething() { synchronized(myLock) {...} } }
委托是建立线程安全类的一个有效手段:只需让现有的线程安全类管理全部的状态便可。 经过多个线程安全类组合而成的类,其线程安全性视状况而定。并发
要在现有的类中添加线程安全操做,有两种方法:线程
public class BetterVector<E> extends Vector<E> { public synchronized boolean putIfAbsent(E x) { boolean absent = !contains(x); if (absent) {add(x);} return absent; } }
扩展的方法比直接修改源代码要脆弱,由于同步策略实现被分布到了多个单独维护的源代码文件中。若是底层的类改变了同步策略并选择了不一样的锁来保护它的状态变量,那么子类会被破坏。 3. 客户端加锁机制 客户端加锁机制是指,对于使用某个对象X的客户端代码,使用X自己用于保护其状态的锁来保护这段客户代码。要使用客户端加锁机制,必须知道对象X使用的是哪个锁。以下代码中,第一个实现版本使用了不一样的锁,因此其并非原子的。设计
public class ListHelper<E> { public List<E> list = Collections.synchronizedList(new ArrayList<E>()); //verson 1 public synchronized boolean putIfAbsent(E x) { boolean absent = !list.contains(x); if (absent) list.add(x); return absent; } //verson 2 public boolean putIfAbsent(E x) { synchronized(list) {//使用list本身的锁 boolean absent = !list.contains(x); if (absent) list.add(x); return absent; } } }
在文档中说明客户代码须要了解的线程安全性保证,以及代码维护人员须要了解的同步策略code