ConcurrentHashMap读写锁

时间:2013-04-19 13:17:09

标签: java multithreading thread-safety concurrenthashmap

我正在尝试找到这些答案,但无法在Google或Java文档中找到答案。

案例1:ConcurrentHashMap中,假设线程 t1 正在从 n 段读取,并且在同一个另一个线程< em> t2 想要写在相同的段n

问题1:这两个操作会一个接一个,还是会同时执行?


案例2:ConcurrentHashMap中,假设线程 t1 正在写 n 段,并且在同一个另一个线程 t2 想要从同一段n

中读取

问题2:这两个操作会一个接一个,还是会同时执行?

2 个答案:

答案 0 :(得分:21)

我认为javadoc会回答你的问题:

  

检索操作(包括get)一般不会阻塞,所以可能   与更新操作重叠(包括put和remove)。检索   反映最近完成的更新操作的结果   坚持他们的发作。对于诸如putAll和。之类的聚合操作   清除,并发检索可能仅反映插入或删除   一些条目。

细分用于更新操作:

  

更新操作之间允许的并发性由   可选的concurrencyLevel构造函数参数(默认为16),即   用作内部尺寸的暗示。

因此,简而言之,读取不会被阻止(它被实现为读取volatile变量)。如果写入在同一段中,则写入可能会相互阻塞。

答案 1 :(得分:1)

根据ConcurrentHashMap Oracle文档,

ConcurrentHashMap的构造函数如下所示:

public ConcurrentHashMap(int initialCapacity,float loadFactor,int concurrencyLevel)

因此上面的行创建了一个具有指定初始容量,加载因子和并发级别的新的空映射。 哪里, 要从ConcurrentHashMap构造函数中考虑的重要参数:

  • initialCapacity - 初始容量。实施执行 内部尺寸以适应这么多元素。
  • concurrencyLevel - 估计并发更新线程的数量。该 实现执行内部大小调整以尝试适应这种情况 很多线程。

在ConcurrentHashMap Api中,您将找到以下常量。

  • static final int DEFAULT_INITIAL_CAPACITY = 16;
  • static final int DEFAULT_CONCURRENCY_LEVEL = 16;

默认情况下,ConcurrentHashMap构造函数(或Object)的初始容量参数和并发级别参数设置为16。

因此,ConcurrentHashMap默认情况下保存了16个锁的列表(锁的数量等于初始容量,默认情况下为16),而不是地图宽锁,而每个锁用于锁定单个存储桶。 Map.This表示16个线程(线程数等于并发级别,默认为16)可以同时修改集合,给定每个线程在不同的存储桶上工作。因此,与hashtable不同,我们执行任何类型的操作(更新,删除,读取,创建),而无需在ConcurrentHashMap中锁定整个映射。

检索操作(包括get)一般不会阻塞。在这种情况下,它使用volatile的概念。,因此可能与更新操作(包括put和remove)重叠。检索反映了最近完成的更新操作的结果。

更新操作之间允许的并发性由可选的concurrencyLevel构造函数参数(缺省值16)引导,该参数用作内部大小调整的提示。该表在内部进行分区,以尝试允许指定数量的并发更新而不会发生争用。因为散列表中的放置基本上是随机的,所以实际的并发性会有所不同。理想情况下,您应该选择一个值来容纳与同时修改表一样多的线程。使用比您需要的值更高的值可能会浪费空间和时间,而显着更低的值可能会导致线程争用。

我希望它有所帮助!