我正在尝试找到这些问题的答案,但无法在 Google 或 Java 文档中找到。
情况 1:在 中ConcurrentHashMap
,假设线程t1正在从段n读取,同时另一个线程t2想要在同一段 n上写入:
问题一:这两个操作是一个接一个,还是同时执行?
情况 2:在 中ConcurrentHashMap
,假设线程t1正在段n上写入,同时另一个线程t2想要从同一段 n中读取,
问题二:这两个操作是一个接一个,还是同时执行?
我正在尝试找到这些问题的答案,但无法在 Google 或 Java 文档中找到。
情况 1:在 中ConcurrentHashMap
,假设线程t1正在从段n读取,同时另一个线程t2想要在同一段 n上写入:
问题一:这两个操作是一个接一个,还是同时执行?
情况 2:在 中ConcurrentHashMap
,假设线程t1正在段n上写入,同时另一个线程t2想要从同一段 n中读取,
问题二:这两个操作是一个接一个,还是同时执行?
我认为 javadoc 回答了你的两个问题:
检索操作(包括 get)一般不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAll 和 clear 等聚合操作,并发检索可能仅反映插入或删除某些条目。
段用于更新操作:
更新操作之间允许的并发性由可选的 concurrencyLevel 构造函数参数(默认为 16)指导,该参数用作内部大小调整的提示。
因此,简而言之,读取不会被阻塞(它被实现为读取 volatile 变量)。如果在同一段中写入,则写入可能会相互阻塞。
根据 ConcurrentHashMap Oracle 文档,
ConcurrentHashMap 的构造函数如下所示:
公共 ConcurrentHashMap (int initialCapacity, float loadFactor, int concurrencyLevel)
因此,上面的行创建了一个具有指定初始容量、负载因子和并发级别的新的空映射。其中,要从 ConcurrentHashMap 构造函数中考虑的重要参数:
在 ConcurrentHashMap Api 中,您将找到以下常量。
ConcurrentHashMap构造函数(或Object)的初始容量参数和并发级别参数默认设置为16。
因此,默认情况下,ConcurrentHashMap 维护了一个包含 16 个锁的列表(锁的数量等于初始容量,默认为 16),而不是 map 范围的锁,每个锁用于锁定 Map 的单个存储桶。这表示16个线程(线程数等于并发级别,默认为16个)可以同时修改集合,假设每个线程工作在不同的桶上。因此,与哈希表不同,我们执行任何类型的操作(更新、删除、读取、创建)而不锁定 ConcurrentHashMap 中的整个映射。
检索操作(包括 get)一般不会阻塞。在这种情况下,它使用了 volatile 的概念。,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在其开始时保持的结果。
更新操作之间允许的并发性由可选的 concurrencyLevel 构造函数参数(默认为 16)指导,该参数用作内部大小调整的提示。该表在内部进行了分区,以尝试允许指定数量的并发更新而不会发生争用。因为哈希表中的放置本质上是随机的,所以实际的并发性会有所不同。理想情况下,您应该选择一个值来容纳尽可能多的线程同时修改表。使用显着高于您需要的值会浪费空间和时间,而显着降低的值会导致线程争用。
我希望它有帮助!