众所周知,HashMap 本身非线程安全的,但是当使用 Collections.synchronizedMap(new HashMap()) 进行包装后就返回一个线程安全的Map。
怎么实现的呢?今天比较有兴趣就看了 Collections.synchronizedMap 的实现,发现其实还是比较简单的。
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) { return new SynchronizedMap<K,V>(m); }
当调用synchronizedMap后返回了一个SynchronizedMap
private static class SynchronizedMap<K,V> implements Map<K,V>, Serializable { // use serialVersionUID from JDK 1.2.2 for interoperability 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) { if (m==null) throw new NullPointerException(); this.m = 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);} } public boolean containsValue(Object value){ synchronized(mutex) {return m.containsValue(value);} } 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);} } public V remove(Object key) { synchronized(mutex) {return m.remove(key);} } public void putAll(Map<? extends K, ? extends V> map) { synchronized(mutex) {m.putAll(map);} } public void clear() { synchronized(mutex) {m.clear();} } private transient Set<K> keySet = null; private transient Set<Map.Entry<K,V>> entrySet = null; private transient Collection<V> values = null; public Set<K> keySet() { synchronized(mutex) { if (keySet==null) keySet = new SynchronizedSet<K>(m.keySet(), mutex); return keySet; } } public Set<Map.Entry<K,V>> entrySet() { synchronized(mutex) { if (entrySet==null) entrySet = new SynchronizedSet<Map.Entry<K,V>>(m.entrySet(), mutex); return entrySet; } } public Collection<V> values() { synchronized(mutex) { if (values==null) values = new SynchronizedCollection<V>(m.values(), mutex); return values; } } public boolean equals(Object o) { if (this == o) return true; synchronized(mutex) {return m.equals(o);} } public int hashCode() { synchronized(mutex) {return m.hashCode();} } public String toString() { synchronized(mutex) {return m.toString();} } private void writeObject(ObjectOutputStream s) throws IOException { synchronized(mutex) {s.defaultWriteObject();} } }
可以看到SynchronizedMap 是一个实现了Map接口的代理类,该类中对Map接口中的方法使用synchronized 同步关键字来保证对Map的操作是线程安全的。