同步容器
[TOC]
Collections返回的线程安全容器
Collections类中有一些方法可以返回线程安全的容器。
public static <T> Collection<T> synchronizedCollection(Collection<T> c);
public static <T> List<T> synchronizedList(List<T> list);
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);
……
底层的实现是通过包装一层函数,给所有原有容器方法都加上 synchronized来同步实现的。下面是SynchronizedMap的源码:
private static class SynchronizedMap<K,V> implements Map<K,V>, Serializable {
private final Map<K,V> m; // Backing Map
final Object mutex; // Object on which to synchronize
SynchronizedMap(Map<K,V> m) {
this.m = Objects.requireNonNull(m);
mutex = this;
}
SynchronizedMap(Map<K,V> m, Object mutex) {
this.m = m;
this.mutex = mutex;
}
public int size() {
synchronized (mutex) {return m.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return m.isEmpty();}
}
public boolean containsKey(Object key) {
synchronized (mutex) {return m.containsKey(key);}
}
//……
}
使用这些线程安全容器的注意事项
在下面几种情况,可能导致线程不安全:
- 复合操作,比如先检查再更新。
- 伪同步,对 synchronized 的操作对象不熟悉,synchronized 必须锁定同一个对象。
- 迭代,单个操作安全,循环迭代并不安全。
推荐的线程安全容器
SynchronizedMap等Collections生成的线程安全容器,使用synchronized来同步,性能较低。
如果有对应的替代类,一般优先使用jdk中专门提供的替代类,比如:
CopyOnWriteArrayList
ConcurrentHashMap
ConcurrentLinkedQueue
ConcurrentSkipListSet