4

ConcurrencyLevel 是否存在某个最佳值,超过该值 ConcurrentHashMap 的性能开始下降?

如果是,该值是多少,性能下降的原因是什么?(这个问题源于试图找出 ConcurrentHashMap 可能具有的任何实际限制)。

4

3 回答 3

5

Javadoc提供了非常详细的指导:

更新操作之间允许的并发性由可选的concurrencyLevel构造函数参数(默认为 16)指导,该参数用作内部大小调整的提示。

该表在内部进行了分区,以尝试允许指定数量的并发更新而不会发生争用。因为哈希表中的放置本质上是随机的,所以实际的并发性会有所不同。理想情况下,您应该选择一个值来容纳尽可能多的线程同时修改表。使用显着高于您需要的值会浪费空间和时间,而显着降低的值会导致线程争用。但是一个数量级内的高估和低估通常不会产生太大的影响。当已知只有一个线程会修改而所有其他线程只会读取时,值 1 是合适的。

总结一下:最佳值取决于预期的并发更新数。一个数量级内的值应该可以很好地工作。超出该范围的值可能会导致性能下降。

于 2012-02-27T13:22:56.457 回答
5

你必须问自己两个问题

  • 我有多少 CPU?
  • 一个有用的程序访问同一个地图的时间百分比是多少?

第一个问题告诉您一次可以访问映射的最大线程数。您可以拥有 10000 个线程,但如果您只有 4 个 cpu,则最多同时运行 4 个。

第二个问题告诉您,这些线程中的大多数都将访问地图并做一些有用的事情。您可以优化地图以做一些无用的事情(例如微基准),但恕我直言,调整没有意义。假设您有一个有用的程序,它经常使用地图。它可能会花费 90% 的时间做其他事情,例如 IO、访问其他地图、构建键或值、使用从地图中获得的值做一些事情。

假设您花费 10% 的时间在具有 4 个 CPU 的机器上访问地图。这意味着平均而言,您将在 0.4 个线程中访问地图。(或者一个线程大约 40% 的时间)在这种情况下,1-4 的并发级别就可以了。

在任何情况下,使并发级别高于您拥有的 cpu 数量可能是不必要的,即使对于微基准测试也是如此。

于 2012-02-27T13:51:32.467 回答
1

从 Java 8 开始,ConcurrentHashMapfor 的构造函数参数实际上concurrencyLevel未使用的,主要是为了向后兼容。该实现被重新编写,以使用每个哈希箱中的第一个节点作为该箱的锁,而不是像早期版本中那样使用固定数量的段/条带。

简而言之,从 Java 8 开始,不必担心设置concurrencyLevel参数,只要根据 API 合约设置一个正(非零、非负)值即可。

于 2017-04-25T04:24:21.490 回答