简述:如何解决HashMap线程不安全的问题?

jdk1.8中HashMap为什么线程不安全?

会出现数据覆盖。
JDK1.7和JDK1.8中HashMap为什么是线程不安全的?

怎么解决HashMap线程不安全的问题?

1.使用HashTable替代HashMap

HashTable的put操作,有synchronized关键字修饰。

2.使用Map map = Collections.synchronizedMap(new HashMap());

这个方法实际上返回了一个SynchronizedMap

SynchronizedMap 实现线程安全的方法也是比较简单的,所有方法都是先对锁对象 mutex 上锁,然后再直接调用 Map 类型成员变量 m 的相关方法。这样一来,线程在执行方法时,只有先获得了 mutex 的锁才能对 m 进行操作。因此,跟 Hashtable 一样,在同一个时间点,只能有一个线程对 SynchronizedMap 对象进行操作,虽然保证了线程安全,却导致了性能低下。这么看来,连 Hashtable 都被弃用了,那性能同样低下的 SynchronizedMap 还有什么存在的必要呢?别忘了,后者的构造方法需要传入一个 Map 类型的参数,也就是说它可以将非线程安全的 Map 转化为线程安全的 Map。

上面这段话出自: Hashtable,SynchronizedMap和ConcurrentHashMap线程安全对比
看看这个类的源码:

    public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
    
    
       return new SynchronizedMap<>(m);
  	 }
  	 
   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的put方法,实际调用的还是HashMap自己的put方法
      public V put(K key, V value) {
    
    
           synchronized (mutex) {
    
    return m.put(key, value);}
       }

3.使用ConcurrentHashMap

jdk1.8中ConcurrentHashMap通过 CAS+synchronized实现线程安全。
Java并发——ConcurrentHashMap(JDK 1.8)

猜你喜欢

转载自blog.csdn.net/zhangjin1120/article/details/121313570