Java 在非选择操作的情况下,HashMap和ConcurrentHashMap之间的主要区别是什么?

Java 在非选择操作的情况下,HashMap和ConcurrentHashMap之间的主要区别是什么?,java,Java,据我所知,在HashMap和ConcurrentHashMap中执行非选择操作时,ConcurrentHashMap会阻止整个段(默认为-16)?区别在于HashMap不是线程安全的,这意味着,如果您有多个线程在使用它,您需要自己处理并发操作。您可以使用Collections.synchronizedMap(map)轻松实现线程安全,它创建了一个包装对象,其中所有方法都是同步的(在该包装对象上)并委托给包装映射。可以看出,这意味着性能差,因为只有一个线程(读写器不重要)可以访问它 正如您所指出的

据我所知,在
HashMap
ConcurrentHashMap
中执行非选择操作时,
ConcurrentHashMap
会阻止整个
段(默认为-16)?

区别在于
HashMap
不是线程安全的,这意味着,如果您有多个线程在使用它,您需要自己处理并发操作。您可以使用
Collections.synchronizedMap(map)
轻松实现线程安全,它创建了一个包装对象,其中所有方法都是
同步的(在该包装对象上)并委托给包装映射。可以看出,这意味着性能差,因为只有一个线程(读写器不重要)可以访问它

正如您所指出的,
ConcurrentHashMap
是线程安全的,并且尝试以与
Collections.synchronizedMap()
稍有不同的方式处理同步。它不使用单个锁,而是尝试使用多个锁,方法是将基础映射划分为个bucket,每个bucket都有一个锁。这样,多个线程可以同时使用映射而不会出现问题,因为它们可能正在处理不同存储桶中的记录。在这种情况下,您不需要锁定整个映射(所有bucket),只需要锁定您感兴趣的记录所在的bucket,这意味着您可以同时对所有bucket执行并行操作。显然,如果所有线程都在同一条记录(或同一个存储桶)上工作,它们仍将像在
Collections.synchronizedMap()
中一样进行同步,并在写入时被阻止。当读线程的数量超过写线程的数量时,这种方法非常好

例如,您可能已经(非常简化):

当您使用键r1对条目执行读/写操作时,地图将选择bucket1,因为该记录应该在那里,并锁定bucket1,仅锁定bucket1。然后,当另一个线程出现时,如果它查询r2,它可以安全地这样做,但是如果它查询r1,它也必须等待bucket1被锁定

当然,所有这些背后都有一个性能损失,但这并不是非常高(尽管我没有任何基准来支持这一说法)

这是否回答了您的问题?

否,在非选择(例如put)操作的情况下,始终在段级别进行锁定

您可以看到ConcurrentHashMap源代码


每当您在并发hashmap上调用put()方法时,它首先计算特定段的哈希位置,然后仅在该段上调用trylock()方法,而不是在表级别。ConcurrenthashMap的结构与简单hashmap不同。 ConcurrentHashMap在初始化时被分成若干段(默认情况下为16段)

它允许相似数量的线程同时访问这些段,以便每个线程在特定段上工作

当一个线程在一个段上工作时,它会将其锁定。它不会阻止其余的线段

如果你想读更多关于它的内容,我建议你链接到下面——用清晰的例子进行很好的解释


什么是“非选择操作”?
ConcurrentHashMap = [ bucket1 = [r1->x], bucket2 = [r2->y], bucket3 = [r3, z] ]