5

我用CopyOnWriteArrayList的蛮多的。当

  • 线程执行大量读取
  • 线程执行一点写操作

但是,我会Collections.synchronizedList()在何时使用

  • 线程执行一点读取
  • 线程执行大量写入

这是因为根据CopyOnWriteArrayList Java Doc

ArrayList 的线程安全变体,其中所有可变操作(添加、设置等)都是通过制作底层数组的新副本来实现的。

这通常太昂贵了,...

说到这里ConcurrentHashMap,我想知道我是否仍然可以在选择ConcurrentHashMap时应用相同的逻辑Collections.synchronizedMap()

ConcurrentHashMap每次我执行写操作时都会制作底层数据结构的新副本吗?如果写操作多于读操作,它的性能会比 Collections.synchronizedMap 差吗?

4

4 回答 4

8

不,ConcurrentHashMap不会制作底层数据结构的新副本。

ConcurrentHashMap是分段映射,分段数基于并发级别。当你写入一个段时,它会被锁定直到写入完成。

于 2013-04-11T08:00:57.537 回答
1

ConcurrentHashMapcheck-then-set几乎总是正确使用它,因为它比同类产品具有更好的性能和更有用的 API(您可以避免线程问题)。
它使用锁剥离来进行更细粒度的访问,并且不复制映射。唯一不应该使用 a
的应用程序是当您需要锁定地图以进行独占访问时。ConcurrentHashMap

于 2013-04-11T07:55:57.847 回答
1

写入时。ConcurrentHashMap它只在内部锁定正在写入的 Map 部分。所以通过这种行为,我们可以很容易地看到它不会生成新副本,而是在同一个副本中进行更改。
因此,当我们尝试写入时,ConcurrentHashMap这意味着我们正在尝试写入任何段,然后它只是锁定该段并仅更新该段。所以简单来说,它永远不会制作任何新副本。所以你的问题的答案是否定的。

于 2013-04-11T08:02:45.713 回答
0

我发现的主要区别是 ConcurrentHashMap 中的自定义“并发级别”。我们可以询问 JVM 需要多少块(段)来划分 Map。将创建许多锁。CopyOnWriteArrayList 使用简单的创建克隆并更新它的简单过程。(这后来被 JVM 与原始数组列表合并。)

于 2019-11-10T02:13:37.140 回答