1.找出構成對象狀態的全部變量; java
2.找出約束狀態變量的不變性條件; 安全
3.創建對象狀態的併發訪問管理策略。 併發
/** * 這裏將mySet實例封閉在PersonSet中, * 儘管HashSet是非線程安全類, * 因爲mySet是私有且不會逸出的, * 咱們經過公共接口提供給外部訪問,但加上了PersonSet內置鎖保護synchronized, * 於是PersonSet是一個線程安全的類 */ @ThreadSafe public class PersonSet { 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); } }
public class PrivateLock { private final Object lock = new Object(); public void methodOne(){ synchronized(lock){ // do sth. } } }
/** * 委託的PersonSet * 將內部操做委託給線程安全的類SynchronizedSet * 從而自身也是線程安全的 */ @ThreadSafe public class DelegatingPersonSet { private final Set<Person> mySet = Collections.synchronizedSet(new HashSet<Person>()); public void addPerson(Person p){ mySet.add(p); } public boolean containsPerson(Person p){ return mySet.contains(p); } }
/** * 將線程安全性委託給多個彼此獨立的狀態變量 * VisualComponent使用CopyOnWriteArrayList(線程安全)來保存監聽器列表 * keyListeners, mouseListeners彼此獨立 * 所以VisualComponent線程安全 */ public class VisualComponent { private final List<KeyListener> keyListeners = new CopyOnWriteArrayList<>(); private final List<MouseListener> mouseListeners = new CopyOnWriteArrayList<>(); public void addKeyListener(KeyListener keyListener){ keyListeners.add(keyListener); } public void removeKeyListener(KeyListener keyListener){ keyListeners.remove(keyListener); } public void addMouseListener(MouseListener mouseListener){ mouseListeners.add(mouseListener); } public void removeMouseListener(MouseListener mouseListener){ mouseListeners.remove(mouseListener); } }
/** * NumberRange不足以保護它的不變性條件 * 併發環境下不安全 */ @NotThreadSafe public class NumberRange { //不變性條件: lower <= upper private final AtomicInteger lower = new AtomicInteger(); private final AtomicInteger upper = new AtomicInteger(); public void setLower(int i){ if (i > upper.get()){ //不安全的檢查 throw new IllegalArgumentException("lower can't > upper"); } lower.set(i); } public void setUpper(int i){ if (i < lower.get()){ //不安全的檢查 throw new IllegalArgumentException("lower can't > upper"); } upper.set(i); } }
/** * 經過擴展實現非重複Vector */ public class NoRepeatVector<E> extends Vector<E> { public synchronized boolean putIfAbsent(E e){ boolean exist = contains(e); if (!exist) add(e); return exist; } }
/** * 這段客戶端代碼看似線程安全, * 但其實並不安全,由於鎖住的對象不正確, * 這裏僅是鎖住ListHelper對象,但list對象並無被鎖住, * 其餘客戶端仍可在不安全狀況下對list進行操做 */ @NotThreadSafe public class ListHelper<E> { public List<E> list = Collections.synchronizedList(new ArrayList<E>()); public synchronized boolean putIfAbsent(E x){ boolean absent = !list.contains(x); if (absent) list.add(x); return absent; } }因此上面的代碼,咱們應該對list加鎖,而不是ListHelper對象:
@ThreadSafe public class SafeListHelper<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; } } }
/** * 經過組合實現"若沒有則添加" 下午4:48:42 */ @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 t){ boolean absent = !list.contains(t); if (absent) list.add(t); return absent; } @Override public synchronized int size() { return list.size(); } ... }
不吝指正。 ide