美文网首页
Map实现线程安全的3种方式

Map实现线程安全的3种方式

作者: Charein | 来源:发表于2019-03-07 20:24 被阅读0次

    我们常用的HashMap不是线程安全的,如果要实现线程安全有3种方式,分别是使用HashTable,使用Colloections的SynchronizedMap方法,使用ConcurrentHashMap

    1. HashTable

    Map<String, Object> map = new Hashtable<>();
    来看看HashTable的源码。

    public synchronized V put(K key, V value) {
          ...
    }
    
    public synchronized V get(Object key) {
          ...
    }
    

    HashTable的get/put方法都被synchronized关键字修饰,说明它们是方法级别阻塞的,它们占用共享资源锁,所以导致同时只能一个线程操作get或者put,而且get/put操作不能同时执行,所以这种同步的集合效率非常低,一般不建议使用这个集合。

    2. SynchronizedMap

    Map<String, Object> map = Collections.synchronizedMap(new HashMap<String, Object>());
    这种是直接使用工具类里面的方法创建SynchronizedMap,把传入进行的HashMap对象进行了包装同步而已,来看看它的源码。

    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;
            }
    
            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);}
            }
            ...
    }
    

    SynchronizedMap的实现方式是加了个对象锁,每次对HashMap的操作都要先获取这个mutex的对象锁才能进入,所以性能也不会比HashTable好到哪里去,也不建议使用。

    3. ConcurrentHashMap

    Map<String, Object> map = new ConcurrentHashMap<>();
    这个也是最推荐使用的线程安全的Map,也是实现方式最复杂的一个集合,每个版本的实现方式也不一样,在jdk8之前是使用分段加锁的一个方式,分成16个桶,每次只加锁其中一个桶,而在jdk8又加入了红黑树和CAS算法来实现。

    虽然实现起来很复杂,但使用起来也是非常简单的,在java面试中问的频率也非常高,最重要的是性能要比上面两种同步方式要快太多,推荐使用。

    参考:面试必问-几种线程安全的Map解析

    相关文章

      网友评论

          本文标题:Map实现线程安全的3种方式

          本文链接:https://www.haomeiwen.com/subject/riwhpqtx.html