ConcurrentHashMap

发布时间:2024年01月15日

? 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖


在这里插入图片描述

1. Hashtable

Hashtable保证线程安全,主要就是给关键方法加上synchronized,相当于直接针对Hashtable 对象本?加锁。
例如:

public synchronized Type put(Type key,Type value){}
public synchronized Type get(Type key,Type value){}
  • 如果多线程访问同?个 Hashtable 就会直接造成锁冲突
  • size 属性也是通过 synchronized 来控制同步,也是?较慢的
  • ?旦触发扩容,就由该线程完成整个扩容过程。这个过程会涉及到?量的元素拷贝,效率会?常低
    在这里插入图片描述

2. ConcurrentHashMap

  1. ConcurrentHashMap最核心的改进就是把一个全局的大锁,改成了每个链表独立的一把小锁。就是把每个链表的头结点作为锁对象(synchronized可以使用任意对象作为锁对象)。大幅度降低了锁冲突的概率。
    在这里插入图片描述
  2. 充分利用CAS特性,把一些不必要加锁的环节省略加锁。
    比如:size属性就通过CAS来更新,避免出现重量级锁的情况。
  3. 读操作没有加锁(但是使?了 volatile 保证从内存读取结果),只对写操作进?加锁。加锁的?式仍然是是? synchronized,但是不是锁整个对象,?是 “锁桶” (?每个链表的头结点作为锁对象),??降低了锁冲突的概率。
    使得读和读、读和写之间都不会有锁竞争。

ConcurrentHashMap的底层编码,在修改的时候会避免使用++ --这种非原子的操作。而使用 = 进行修改(原子的)。
读的时候,要么读到的是写之前的旧值,要么是读到写之后的新值,不会出现读到一个一半的值。

  1. 优化了扩容?式: 化整为零,多次搬运
    发现需要扩容的线程,只需要创建?个新的数组,同时只搬?个元素过去。
    扩容期间,新?数组同时存在。后续每个来操作 ConcurrentHashMap 的线程,都会参与搬家的过程,每个操作负责搬运??部分元素。搬完最后?个元素再把?数组删掉。
    这个期间,插?只往新数组加。但查找需要同时查新数组和?数组

Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类的。ConcurrentHashMap是HashTable的替代,比HashTable的扩展性更好。

文章来源:https://blog.csdn.net/iLoyo_/article/details/135606970
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。