简介
由于在多线程场景下,使用HashMap、LinkedList等容器,会带来线程安全的问题,那么如果需要线程安全的容器该怎么做?一是使用java.util.concurrent下提供的并发容器,二是使用java.util.Collections下的Collections.synchronzedXXX()方法(静态内部类的构造方法)。
如何使用
当需要一个线程安全的HashMap时,可以将HashMap丢给Collections.synchronzedMap(),会生成一个名为SynchronizedMap的Map。代码如下:
public static Map map = new Collections.synchronizedMap(new HashMap());
JDK内部得到实现原理如下:
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;
}
SynchronizedMap(Map<K,V> m, Object mutex) {
this.m = m;
this.mutex = mutex;
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}
....
}
SynchronizedMap通过加入mutex,用synchronized (mutex)将对m的操作包裹,达到线程安全的,如上段代码中的get()。事实上不只get()方法是这样,如下图:
这样就导致了在多线程环境下,其性能表现不够好。无论是增删改查,还是查看大小等操作,都需要获得mutex锁,这就导致大多数操作是在等待状态,等待锁的释放。在一般情况下够用,但在高并发的情况下,还是使用java.util.concurrent下提供的并发容器,这些容器专门进行了性能优化,更适合高并发场景。