使容器线程安全
Collections提供了一些让线程安全的函数
jdk 1.8
Collections.synchronizedMap(new HashMap<>());
...
Collections.synchronizedSet(new HashSet<>());
比如 Collections.synchronizedMap(new HashMap<>()) 它通过传入的对象实例化Collections的子类SynchronizedMap的每一个方法,在通过获取对象锁,实现线程安全
jdk 1.8
private static class SynchronizedMap<K,V>
implements Map<K,V>, Serializable {
private static final long serialVersionUID = 1978198479659022715L;
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;
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
public V put(K key, V value) {
synchronized (mutex) {return m.put(key, value);}
}
...
}
CAS,Compare And Swap
鉴别线程是否冲突,若遇冲突,则重试当前操作
主要三个参数,V-要更新的变量,E-预期的变量,N-新值,当V和E相等时,才将N替换V
线程安全的容器
ConcurrentHashMap
ConcurrentHashMap默认被细分为16个段,每一个段都是一个细粒度的HashMap,通过put(K key,V value),会根据hashcode获得在哪一个段,对该段加锁,实现线程安全,同样size()会对每一个段加锁,等于对整个ConcurrentHashMap加锁,在求大小总和
CopyOnWriteArrayList
对读-读、读-写不阻塞,只对写-写阻塞
jdk 1.8
public E set(int index, E element) {
synchronized (lock) {
Object[] es = getArray();
E oldValue = elementAt(es, index);
if (oldValue != element) {
es = es.clone();
es[index] = element;
}
// Ensure volatile write semantics even when oldvalue == element
setArray(es);
return oldValue;
}
}
public boolean add(E e) {
synchronized (lock) {
Object[] es = getArray();
int len = es.length;
es = Arrays.copyOf(es, len + 1);
es[len] = e;
setArray(es);
return true;
}
}
ConcurrentLinkedQueue
使用CAS实现线程安全