ConcurrentHashMap

1 map的分类

(1)非线程安全的map:
    HashMap
(2)线程安全的map:
    HashTable   Collections.synchronizedMap(new HashMap<K, V>())   ConcurrentHashMap

2 各个map的比较

(1)HashMap:非线程安全的,适用于单线程环境,因为不存在锁和阻塞,所以效率较高
(2)HashTable:线程安全的,使用synchronized关键字修饰方法,实现了线程安全。单线程环境下,建议使用HashMap,因为锁的管理也需要开销。
(3) Collections.synchronizedMap(map):线程安全的,使用Collections里面的静态方法将非线程安全的map封装成线程安全的map。效率和应用场景方面与HashTable相同。
(4) ConcurrentHashMap:一个专用于高并发的map。使用了分段锁机制,减小锁粒度,因此提高了并发度。

3 ConcurrentHashMap浅析

3.1 底层存储结构图


3.2 分段锁

    ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

    ConcurrentHashMap是专门为线程并发而设计的,它的get操作是无锁的,它的put操作只在对应的segment上加锁。因此,它的整体性能优于同步的HashMap(对整个table加锁)。
    默认情况下,ConcurrentHashMap拥有16个段,因此,足够幸运的话,可以同时接受16个线程同时put(插入到不同段中)。

3.3 弱一致性问题

    由于get方法,并没有加锁,因此肯定会存在一致性的问题。get方法并没有加锁,因此也不会和put方法冲突,当多个线程同时操作该map时,有的线程get,有的线程put,因为我们并不确定put方法执行完了没(可能只执行了一部分语句,后面真正改内存的语句还没有执行),所以get不一定能够得到最新值(put还没写进去,叫最新值也不是很妥当)。但是,一旦put操作执行完,那么get一定可以感知到最新值,因为Node的val和next字段都是volatile的:

 static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;
}

  同理,很多全局方法都存在弱一致性问题,比如size等。

   ConcurrentHashMap的弱一致性主要是为了提升效率,是一致性与效率之间的一种权衡。要成为强一致性,就得到处使用锁,甚至是全局锁。

  上面仅是个人的一点浅见,有不妥之处欢迎指出。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值