JDK8中ConcurrentHashmap代码解释

2023-11-26

我一直在尝试理解 JDK8 中的 ConcurrentHashMap 函数,与 JDK7 中的函数相反(除了源代码之外,还可以找到一些好人(例如 Richard)对其进行了很好的解释http://www.burnison.ca/articles/the-concurrency-of-concurrenthashmap)。看起来 JDK8 中已经发生了很大的变化 - 例如本身不再有“段”,但不知何故,我有一种感觉,这些更改是为了使代码更简单?

  1. 我在理解方法 ConcurrentHashMap.putVal(...) 时遇到一些困难,尤其是以下部分 - 是否直接锁定“段”列表的头部以插入 else{} 中?:

        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);
        else {//...}
    
  2. 也不太确定 ConcurrentHashMap.casTabAt(...) 的代码。

  3. 另外,关于JDK8中ConcurrentHashMap.get(Object key)的源代码,它是否严格没有锁(我没有看到任何锁,如果是这样,它如何在没有锁的情况下工作,因为我没有看到循环'再次尝试?)或者有某种我没有观察到的乐观锁?

如果有人可以提供一些提示,我们将不胜感激。


有关putVal(K key, V value, boolean onlyIfAbsent) method

每个垃圾箱/桶包含一个hash领域,它以一种非常聪明的方式结合了两个目的:

  • 对于常规 bin(大多数 bin 只包含单个项目),它存储映射到此处的键的哈希码。但最高位被清除(它始终设置为 0)。
  • 对于特殊的 bin(目前有 3 种类型),它包含一个特殊的负值。聪明的部分是,您只需要顶部位即可区分正值和负值,从而区分常规垃圾箱和特殊垃圾箱。区分不同类型的特殊 bin 可以自由使用剩余的 31 位。

本节

else if ((fh = f.hash) == MOVED)
    tab = helpTransfer(tab, f);
else {//...}

是发现映射不为空并且您尝试映射的键的存储箱不为空后进行的第一次检查。

如果您找到的垃圾箱是特殊类型的垃圾箱之一 - 转发垃圾箱,则满意。需要转发箱,因为调整大小是同时迭代完成的,并且已经传输(到新表)的条目仍然需要可访问(通过旧表中的转发箱)。

有关casTabAt((Node<K,V>[] tab, int i, Node<K,V> c, Node<K,V> v) method

The casTabAt()方法用于使用对象引用的比较和交换操作以原子方式设置映射条目。您仍然可以在几乎所有需要的地方看到典型的 CAS 循环casTabAt()使用 - 您构造要放置的对象,然后尝试将其 CAS 到其正确的位置。如果在 CAS 尝试之前进行复杂的构造感觉很奇怪,你可以看看 Jeff Preshing 的您可以执行任何类型的原子读-修改-写操作.

从某种意义上说,ConcurrentHashMap仍然使用条带锁定,但具有更精细的锁定粒度(竞争区域现在从多仓段到单个仓最小化)并且锁几乎完全被 CAS 操作取代。

有关get(Object key) method

The get()方法可以在没有任何锁定的情况下逃脱,因为在大多数情况下,bin 内容是使用设置和检索的volatile语义(通过前面提到的casTabAt()方法及相关tabAt()方法)。如果 bin 包含映射到同一个 bin 的红黑树条目,情况会更加棘手,并且您可以看到访问的条目内的遍历TreeBin总是在 a 中完成synchronized block.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JDK8中ConcurrentHashmap代码解释 的相关文章

随机推荐

  • 如何在 C 中声明可变大小的二维数组?

    我的一个项目有问题 我必须制作一个可变大小的二维数组来存储一些预测误差 所以这是关于图像的 问题是我必须加载不同尺寸的图像 因此对于每个图像 我必须将具有相应像素数的二维数组放入文件中 我已经在您的问题中进行了搜索 但这不是我想要的任何人都
  • WPF 组合框绑定

    我有两个组合框 它们都与相同的源绑定
  • 如何重新加载 Rails 3 中的所有 gem?

    有没有办法在不完全重新启动服务器的情况下重新加载 Rails 应用程序中的所有 gem 我有一个 Gemfile 使用 path引用我在同一系统上开发的依赖项 并且必须杀死该应用程序并执行此操作很烦人rails s每次我保存更改时都会再次出
  • VB.NET 和 sizeof

    我正在将一些代码从 C 转换为 VB NET 我在 C 中有以下行 var bytes new byte password Length sizeof char 看着MSDN看来VB NET似乎没有sizeof操作员 我明白有一个Marsh
  • 在 Android 1.5 + 上访问视频和照片

    因此 我尝试允许用户使用此处描述的方法通过我的 Android 应用程序选择特定的媒体 从我的 Android 应用程序中的图片应用程序访问图片 它工作得很好 除了这样一个事实 我似乎只能在视频或照片之间进行选择来向用户展示 而不能同时选择
  • Clojure:列出在命名空间内实现某些协议的所有定义类型

    我有一个协议和几个在一个工作区中实现它的定义类型 如何列出实现以下协议的所有定义类型 我已经找到了从 ns public 过滤数据的解决方案 但我不喜欢它 因为它使用了一些 魔法 来完成工作 因为我还没有找到实现我的目标的正确方法和满足吗
  • 类型“System.Data.Linq.DataContext”是在未引用的程序集中定义的

    问题 转到特定页面时出错 在本地调试中 CS0012 类型 System Data Linq DataContext 是在未引用的程序集中定义的 您必须添加对程序集 System Data Linq Version 4 0 0 0 Cult
  • 长宽比错误的 iTunes Connect 屏幕截图

    在模拟器中拍摄了每种尺寸的屏幕截图 我仅在 4 7 英寸 iphone 6 和 5 5 英寸 iphone 6 Plus 屏幕截图上遇到问题 4 英寸和 3 5 英寸上传没有问题 错误状态 一张或多张屏幕截图的宽高比不正确 有关更多信息 请
  • 预处理器计数器宏

    有没有办法创建一个COUNTER 扩展为每次加一的数字的宏 遵循 C 11 14 标准 COUNTER 被调用 我想过 但找不到让它发挥作用的方法 我没有找到一种方法来存储 状态 COUNTER macro Example define C
  • 查看链接服务器依赖关系sql server 2008

    有谁知道如何 是否可以查看依赖于 Sql Server 2008 中链接服务器的所有表 视图 存储过程 基本上就像链接服务器可以访问上下文菜单 查看依赖项 一样 非常感谢任何帮助 Thanks 搜索它 SELECT OBJECT NAME
  • is_file 与 file_exists 的性能以及 PHP 中的缓存?

    我做了一些测试来比较和测量这两个函数的速度 is file似乎比这快几倍 我都使用了 10000 次迭代 文件已存在 我想知道 PHP 或操作系统是否为这些功能使用一些缓存 或者总是访问 HDD 我想不会 但我想知道 我使用了这段代码
  • Google CoLab - 如何运行 CoLab 环境“文件”选项卡(即 /content/)中的 jupyter 笔记本文件

    在 Google CoLab 中 左侧是一个可以打开的窗格 其中显示Table of Contents Code snippets and Files 在里面Files窗格中有一个上传按钮 我可以将笔记本文件上传到此Files区域 但是 一
  • 如何在 MATLAB 中将两个图例添加到单个图中?

    我想在 MATLAB 中的绘图中添加两个图例 我怎样才能做到这一点 您可以创建第二个叠加轴 并带有自己的图例 当然在不同的位置 EDIT 这是一个简单的例子 create some plot with a legend hAx 1 axes
  • 返回一行中正则表达式搜索的第二个实例

    我有一个文件 其中包含特定的感兴趣行 例如第 12 行 如下所示 conform 244216 packets exceed 267093 packets 我编写了一个脚本来通过正则表达式提取第一个数字并将该值转储到新文件中 getexce
  • 如何使用 Phonegap 打开 Twitter 和 Facebook 应用程序?

    我正在尝试使用我的 PhoneGap 应用程序链接来打开 Twitter 应用程序中的特定用户个人资料页面 我知道并不是每个人的设备上都安装了 Twitter 应用程序 所以如果他们没有安装 我想将他们发送到 Play 商店下载 问题是 每
  • Python 字典中键的多个值

    我想做的是将键中的 3 个值获取到单独的变量中 目前我正在这样做 for key in names posX names key 0 posY names key 1 posZ names key 2 尽管它有效 但对我来说似乎不太直观 我
  • Rapidjson 提取键和值

    我试图提取数组中对象的键和值 但找不到正确的 getter for Value ConstValueIterator itr document params Begin itr document params End itr for Val
  • 我应该考虑 memmove() O(n) 还是 O(1)?

    这可能是一个愚蠢的问题 但我想计算我的一种算法的复杂性 并且我不确定要考虑什么复杂性内存移动 功能 你能帮忙 解释一下吗 void memmove void destination const void source size t num
  • Angular:如何使链接跳转到同一页面中的某些部分

    我想要一个锚链接使用 id 标签跳转到同一页面中的特定部分 这是我的html div class nav container ul class nav text center li class active a href account s
  • JDK8中ConcurrentHashmap代码解释

    我一直在尝试理解 JDK8 中的 ConcurrentHashMap 函数 与 JDK7 中的函数相反 除了源代码之外 还可以找到一些好人 例如 Richard 对其进行了很好的解释http www burnison ca articles