-
很多情況下應(yīng)該重用現(xiàn)有的類, 添加自定義的功能, 此時(shí)需要在不破壞線程安全性的情況下添加新的操作
(1) 方法一: 直接修改原始的類
優(yōu)點(diǎn): 同步策略仍然處于同一個(gè)源代碼文件中, 更容易理解和維護(hù)
缺點(diǎn): 常常無(wú)法修改源代碼
(2) 方法二: 擴(kuò)展這個(gè)類
同步策略分布到了各個(gè)文件中, 并且要確定的得知基類的同步策略
示例
@ThreadSafe
public class BetterVector<E> extends Vector<E> {
// When extending a serializable class, you should redefine serialVersionUID
static final long serialVersionUID = -3963416950630760754L;
public synchronized boolean putIfAbsent(E x) {
boolean absent = !super.contains(x);
if (absent) {
super.add(x);
}
return absent;
}
}
(3) __方法三: 客戶端加鎖機(jī)制__
擴(kuò)展類的功能, 但不是擴(kuò)展類本身, 而是將擴(kuò)展代碼放入__輔助類__中
__客戶端加鎖__: 對(duì)于使用某個(gè)對(duì)象X的客戶端代碼, 使用__X本身用于保護(hù)其狀態(tài)的鎖__來(lái)保護(hù)這段客戶代碼
__所以, 使用客戶端加鎖方式, 必須從源碼中找到X使用的是哪一個(gè)鎖__
示例
錯(cuò)誤示例
@NotThreadSafe
class BadListHelper<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;
}
}
正確示例
@ThreadSafe
class GoodListHelper<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;
}
}
}
正確示例和錯(cuò)誤示例的區(qū)別在于使用鎖的不同, 深入Collections.synchronizedList的源碼, 會(huì)發(fā)現(xiàn)它使用的鎖就是Collections.synchronizedList對(duì)象本身, 所以輔助類中也要使用Collections.synchronizedList本身作為鎖
和方法二一樣, 客戶端加鎖方式也存在同步策略分布在各個(gè)類中的問(wèn)題, 這樣當(dāng)?shù)讓釉创a的同步策略改變時(shí)可能會(huì)不穩(wěn)烛芬。
(4) __方法四: 組合__
__使用Java監(jiān)視器模式, 對(duì)內(nèi)部的對(duì)象完全由類本身提供的鎖保護(hù), 不管底層的類是否線程安全__
示例
@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;
}
// Plain vanilla delegation for List methods.
// Mutative methods must be synchronized to ensure atomicity of putIfAbsent.
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 synchronized void clear() {
list.clear();
}
public synchronized boolean add(T e) {
return list.add(e);
}
public synchronized boolean remove(Object o) {
return list.remove(o);
}
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 boolean containsAll(Collection<?> c) {
return list.containsAll(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);
}
}
所有需要同步的方法都使用ImprovedList本身的鎖, 而不必在意封裝對(duì)象的同步策略
-
同步策略應(yīng)該文檔化
定義好
(1) 哪些變量為volatile
(2) 哪些變量用鎖保護(hù)
(3) 哪些變量必須不可變或者線程封閉
(4) 哪些操作必須是原子操作
等……