资讯专栏INFORMATION COLUMN

Java容器类研究9:其它Map

zilu / 221人阅读

摘要:和的区别和的区别是,在操作的方法上加入关键字,使得线程安全。使用进行比较,或者传入的比较器。基于,它自己的任务主要是维护保持顺序的双向链表。和的区别提供了一个高效的线程安全的访问和更新的方式。在中的过程和类似。

HashTable和HashMap的区别

HashTable和HashMap的区别是,HashTable在操作table的方法上加入synchronized关键字,使得线程安全。实现方式和HashMap类似,但是HashTable没有处理在某个槽下的值太多,链表过长的情况。

TreeMap和HashMap的区别

有序,二叉搜索树,使用红黑树。使用key进行比较,或者传入的比较器。方法containsKey、get、put和remove的时间复杂度是log(n)。

LinkedHashMap与HashMap的区别

LinkedHashMap保存了元素的插入顺序,在遍历时会遵循插入的顺序。而HashMap遍历时,顺序是按照table的顺序,依次遍历每一个槽中的链表,所以顺序和插入顺序完全不同。

LinkedHashMap在Node上加上了beforeafter属性用以构建保持原顺序的双向链表。

LinkeHashMap可以设置参数,使其从插入顺序变为访问顺序。

LinkedHashMap基于HashMap,它自己的任务主要是维护保持顺序的双向链表。

ConcurrentHashMap ConcurrentHashMap和HashMap的区别

java.util.concurrent;

ConcurrentHashMap提供了一个高效的、线程安全的访问和更新HashMap的方式。较之HashTable,它没有提供在整个table上的锁,同步方式粒度更细。

如何实现并发访问的安全

看网上资料,旧版本的ConcurrentHashMap采用了分段的策略进行同步。Hash步骤如下:

ConcurrentHashMap维护了一个segment数组,segment是一个锁。

将key先hash到segment位置,每个segment存储了一个真正的table。

再次hash,找到在table中的位置。

在table中的过程和HashMap类似。

所有并发访问ConcurrentHashMap的线程会在每个segment上同步,所以线程可以并行的访问不同的segment,减小了同步的粒度。

但是,在1.8中,使用的是sun.misc.Unsafe工具。它的作用有:

对变量和数组内容的原子访问,自定义内存屏障

对序列化的支持

自定义内存管理/高效的内存布局

与原生代码和其他JVM进行互操作

对高级锁的支持

ConcurrentHashMap对table的操作全部由sun.misc.Unsafe来完成:

    static final  Node tabAt(Node[] tab, int i) {
        return (Node)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
    }

    static final  boolean casTabAt(Node[] tab, int i,
                                        Node c, Node v) {
        //c表示旧值
        //v表示新值
        //更新前会验证旧值是否变化,如果变化说明期间被其它线程修改,则修改失败
        //外部使用该方法一般会使用一个循环,以多次重试
        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
    }

    static final  void setTabAt(Node[] tab, int i, Node v) {
        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
    }

可以简单的理解为上述方法是原子性的,对目标数据所在的内存位置进行了加锁,整个操作过程中,对该部分内存的读、写不会受其它线程的影响。可见,该方法的并发实现粒度更细。

还有一点需要注意,在并发操作时,可能会出现有的线程开始扩张或缩小table,但是有的线程却试图操作table的情况。因为搬迁table上元素的过程比较耗时,所以,其它线程发现该table正在重建,会先将操作table的事情往后放一放,而是转头去帮助搬迁table,等table搬迁完毕再继续自己的活。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67915.html

相关文章

  • Java 基础 | Collection 集合概览

    摘要:说到复盘基础,并不是所有的都会复盘,没那个时间更没那个必要。比如,一些基础的语法以及条件语句,极度简单。思前想后,我觉得整个计划应该从集合开始,而复盘的方式就是读源码。通常,队列不允许随机访问队列中的元素。 ​showImg(https://segmentfault.com/img/remote/1460000020029737?w=1080&h=711); 老读者都知道,我是自学转行...

    codergarden 评论0 收藏0
  • Java容器研究8:HashMap

    摘要:的值是在上述方法中处理过的值,通过与当前容量进行,直接获取到哈希表的位置。策略二,如果已经很大了,扩容已经不可取,那么就采用红黑树结构转化链表。红黑树的创建不再详述。红黑树的根就是中第一个节点。 java.util.Map Map中的自我引用 需要小心用易变的对象作为Map的key,这会导致Map的行为无法预测。Map也不可以将自己作为key,可以作为value,但是会导致equals...

    zhichangterry 评论0 收藏0
  • Python进阶:设计模式之迭代器模式

    摘要:抓住了迭代器模式的本质,即是迭代,赋予了它极高的地位。输出结果输出结果小结迭代器模式几乎是种设计模式中最常用的设计模式,本文主要介绍了是如何运用迭代器模式,并介绍了模块生成迭代器的种方法,以及种生成迭代器的内置方法。 showImg(https://segmentfault.com/img/bVbmv7W?w=4272&h=2848); 在软件开发领域中,人们经常会用到这一个概念——设...

    pubdreamcc 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<