【问题标题】:Java ConcurrentHashMap implementationJava ConcurrentHashMap 实现
【发布时间】:2012-09-04 17:51:15
【问题描述】:

我刚才在看Java的ConcurrentHashMap的源码,发现这行代码:

/*
 * The maximum number of times to tryLock in a prescan before possibly blocking on acquire in   
 * preparation for a locked segment operation. On multiprocessors, using a bounded number of  
 * retries maintains cache acquired while locating nodes.
 */
static final int MAX_SCAN_RETRIES =
              Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1

MAX_SCAN_RETRIES 用于在获取锁时查找条目。我的问题是如何为多处理器机器确定数字64?有人知道64这个数字背后的原理吗?

【问题讨论】:

  • 供参考,来源可以找到here。那里的 javadoc 是:“在可能阻塞获取以准备锁定段操作之前,在预扫描中 tryLock 的最大次数。在多处理器上,使用有限的重试次数来维护在定位节点时获取的缓存。”
  • 我的错,我误解了你为什么要评论它。删除该评论。
  • Doug Lea 是这样吗?他似乎编写了该课程:)
  • 这个问题出色地展示了良好评论的价值。 (或者在这种情况下,缺少它。)
  • 我可能错了,但我猜“每个 Java 虚拟机线程都有自己的 pc(程序计数器)寄存器”说明了为什么选择 64 位。我还在尝试弄清楚多处理器和pc寄存器的关系)docs.oracle.com/javase/specs/jvms/se5.0/html/Overview.doc.html

标签: java


【解决方案1】:

在处理跨多个 CPU 的锁重试时,您需要在尝试快速获取锁(自旋)和允许 CPU 切换到另一个线程以避免浪费 CPU 时间在未旋锁上的锁之间取得平衡即将发布。允许 CPU 尝试获得锁的实际自旋次数受到整个系统的实际速度以及通常在临界区中执行的代码量的强烈影响。

这个问题深深植根于停止问题以及与 SMP 系统上的操作系统设计相关的许多其他问题,以优化并发性。这种设计选择通常是通过在许多应用程序中反复试验的方法来解决的。但是,在我看来,选择 64 就像是实现者的任意调用(数字是 2 的幂)。

不幸的是,这个特定的代码既有错误又有限制。错误在于 availableProcessors 的文档指出“此值可能会在虚拟机的特定调用期间发生变化”,因此可能导致锁旋转太多次(如果计数从 > 1 移动到 = 1)或太少(在反之亦然)。这是一个限制,因为 MAX_SCAN_RETRIES 是最终的,真正需要在他们的应用程序中调整并发性的开发人员没有能力这样做(尽管反射可能会玩一些技巧)。

【讨论】:

  • 你的批评似乎有点牵强。我想不出很多(任何?带热插拔CPU的系统?)在jvm运行时availableProcessors会发生有意义变化的情况。此外,我非常怀疑调整该特定参数是否会对 99% 的程序产生很大影响(因此提供调整它的能力值得增加代码维护)。
  • @biziclop - 是的,这也发生在我身上(这些天我不是 vmware vm 中所有可用功能的专家)。仍然不确定人们多久将 cpus 换入和换出 vmware(或类似)虚拟机。根据these results(请注意,拔出对任何人都不起作用),我假设它的使用可能稀缺似乎并不遥远。
  • @jtahlborn 他们现在可能不会这样做,但请记住,这是 Java 发行版的标准类。话虽如此,答案的措辞确实听起来有点刺耳。
  • @jtahlborn - 我不同意,在许多企业架构中热插拔 CPU 很常见(查看 IBM 服务器)。这在此类系统上并不罕见。无论如何,事实是这种参数应该有一个合理的默认值,并且应该在必要时进行调整。
  • 对,但我们关心的唯一情况是 1 到 >1(不是 2 到 3,或 3 到 4 等...)。无论如何,我的观点只是你所说的代码是“错误的和限制的”充其量是误导性的。我想几乎没有人会实际上在实际运行的系统中关心这个值(这就是它的编码方式,对于世界上 99% 的人来说,这是一个合理的默认值,它也可能适用于剩下的 1%)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 2011-11-05
  • 1970-01-01
  • 2010-09-21
  • 2011-02-19
  • 2014-01-10
  • 2020-08-22
相关资源
最近更新 更多