说说concurrenthashmap的底层实现?说说hashmap和concurrenthashmap的区别

说说concurrenthashmap的底层实现

  1. concurrenthashmap是安全的hashmap,它底层数据结构使用的是数组+链表+红黑树。
  2. 通过hashcode函数获取哈希值,然后哈希值与数组容量减一进行按位与算出存放的数组下标,再通过equals来判断是否重复,以链表或者红黑树的方式存放下标相同的节点。因此要放入concurrenthashmap的对象应该重写hashcode和equals方法。
  3. 它的默认初始化容量是16,如果使用有参构造,参数为n,那么初始化容量就是不小于1.5n+1的最小2的n次方值。然后会将容量值放在sizeCTL中。
  4. 初始化操作在第一次put元素的时候进行,如果table为空,就会进行初始化,创建大小为sizeCTL的node数组。
  5. key和value都不能为null。
  6. 如果sizeCTL的值为正数,如果数组已经初始化,那么该值就是下一次扩容的阈值,如果还没初始化,那么这个就是初始化容量。如果为负数,-1的话,就代表数组正在初始化。非-1的负数,代表正在扩容,值是扩容线程的个数,本线程也会进入协助扩容。
  7. 默认加载因子也是0.75,和hashmap一样。容量占满table数组的75%之后就会扩容,扩容为原容量的两倍。并且有协助扩容机制,每个进入扩容的线程都会分配到扩容任务,一般任务大小是总容量/8,如果得到的值小于16,那么任务大小就按16来分。从后往前进行迁移。
  8. 当链表长度达到8,变成红黑树。当红黑树节点数少于6就会变回链表。
  9. 并发度默认是16,也就是底层数组的长度。
  10. 底层的实例变量大部分都有volatile关键字修饰,这样可以确保对变量的修改对其他线程是可见的。并且还有transient修饰,数据无法被序列化,确保数据安全。
  11. 为什么需要将容量设置为2的n次方? 因为底层查找元素插入数组的位置用的是数组容量n减一和hash值进行按位与得到下标,如果是2的n次方,那么n-1得到的就是后面是全1,进行按位与可能得到的结果刚好覆盖了数组的所有位置。
  12. 为什么要将传入的参数乘1.5+1来获取初始化容量?因为如果按照传入的参数来初始化容量,事实上并未完全避免扩容,在填满数组的75%的时候还是会进行扩容。
  13. 底层是靠CAS+synchronized确保多线程安全的,初始化的时候,使用CAS进行初始化,有线程已经在初始化了,其他线程看到标志位知道有线程在初始化,就会让出CPU,然后一直循环。等待初始化完成。
  14. CAS是指一个线程修改某一个资源之前会先记录原来的值,然后进入修改,修改完毕之后出来查看资源是否和原来记录的一样,一样的话代表期间资源没有被其他线程改过,就可以提交修改。如果不一样,就撤销修改,重新获取当前资源,继续进入修改,一直到成功。不过这样会有ABA问题,就是资源事实上已经被修改过,不过又修改回来了,可以通过添加版本号来解决。
  15. concurrenthashmap性能比hashtable高的原因,主要是因为它锁的是链表的头节点,而hashtable锁的是整个数组。锁头节点,不同链表的添加操作彼此不影响,效率较高。而且很多地方concurrenthashmap都尽量避免用锁,转而使用CAS机制。put的时候会用锁,扩容数组迁移的时候也会使用锁。

说说hashmap和concurrenthashmap的区别

  • 前者是线程不安全的,后者是线程安全的。
  • 前者的自定义初始化容量是大于等于参数的最小2的幂次方值。(如果参数是32,那么实际就是32,如果参数是31,实际也是32.。后者的自定义初始化容量是大于等于参数*1.5+1的最小2的n次方。(如果参数是32,那么实际是64.)
  • 前者扩容是一个线程扩容,后者可以多个线程一起进行扩容。(加快扩容速度)
  • hashmap可以键或者值为空,而currenthashmap键和值都不能为空。
  • currenthashmap底层的数据结构基本都有volatile修饰来确保可见性,而hashmap没有。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值