2

在 ConcurrentHashMap 中有分段的概念。如果两个线程试图访问 ConcurrentHashMap 意味着什么,它们被分成两个块,块的默认大小为 16。

现在假设在 ConcurrentHashMap 只有两个元素并且有两个不同的线程出现并且 thread1 尝试修改第一个值而 thread2 尝试修改第二个值的场景中。在这种情况下 ConcurrentHashMap 是否会进行分段?

现在在不同的情况下,两个线程都尝试修改相同的值 ConcurrentHashMap 将如何处理这种情况?通过使用锁定机制还是有别的东西?

4

3 回答 3

4

ConcurrentHashMap 有几个桶。键根据其哈希值映射到其中一个桶中。当您添加或检索值时,与该键关联的存储桶将被锁定。

对于您的第一个问题,有两种可能性:两个密钥都位于同一个存储桶中,或者它们位于不同的存储桶中。在第一种情况下,一次只能有一个线程工作——第一个获得锁的线程将抓住它并工作,第二个线程将等待轮到它。在第二种情况下,密钥位于不同的存储桶中,它们将各自获取独立的锁并同时执行它们的工作。

对于您的第二个问题,它是被锁定的存储桶,仅此而已。如果两个线程尝试为同一个键存储两个值,则 ConcurrentHashMap 承诺这两个值之一将与该键相关联。,如果线程 A 运行map.put("Answers",2);并且线程 B 运行map.put("Answers",10);,则 ConcurrentHashMap 将确保映射是有效的并包含其中一个210for "Answers",但它不会对这两个中的哪一个做出任何承诺。

于 2013-04-09T18:25:40.100 回答
3

CHM 保证这些操作(例如put,putIfAbsent等)不会重叠,是的,这是通过锁定完成的。CHM 的每个段都有自己的锁,只要您修改该段,就会获取该锁。

(作为参考,正如@Affe 指出的那样,如果您正在修改中的值的内容ConcurrentHashMap,CHM 不会做 - 不能做 - 任何使该线程安全的事情。)

于 2013-04-09T18:15:37.127 回答
0

首先,CHM 的新实现根本不使用 Segments,它仍然使用节点数组,如果给定索引中的节点不存在并且两个线程试图插入两个条目,其哈希码等于给定索引,则 CHM使用 CAS ,否则如果节点存在,则 CHM 使用该节点的第一个元素上的锁定来放置新值。CHM 中的读取是非阻塞的,并且在 Unsafe 类的原子读取的帮助下使用发生在保证之前。查看我关于 CHM 的博客了解更多详情 https://strogiyotec.github.io/pages/posts/chm.html

于 2020-11-01T17:36:13.613 回答