ConcurrentHashMap vs同步HashMap

HashMapConcurrentHashMap上使用包装类SynchronizedMap什么区别? 它只是能够修改HashMap而迭代它( ConcurrentHashMap )?

同步HashMap

  1. 每个方法都使用对象级别locking进行同步。 所以synchMap上的get和put方法获得一个锁。

  2. locking整个集合是一个性能开销。 当一个线程持有锁时,其他线程不能使用该集合。

ConcurrentHashMap是在JDK 5中引入的。

  1. 在对象级别没有locking,locking的粒度更加精细。 对于ConcurrentHashMap ,锁可能位于hashmap存储桶级别。

  2. 较低级别locking的效果是,您可以使同步读取器和写入器不可能用于同步集合。 这导致更多的可扩展性。

  3. 如果一个线程试图修改而另一个线程正在迭代,则ConcurrentHashMap不会抛出ConcurrentModificationExceptionexception。

这篇文章Java 7:HashMap vs ConcurrentHashMap是一个非常好的阅读。 强烈推荐。

简短的回答:

这两个映射都是Map接口的线程安全实现。 ConcurrentHashMap在预计高并发的情况下实现更高的吞吐量。

Brian Goetz关于ConcurrentHashMap背后思想的文章是非常好的读物。 强烈推荐。

ConcurrentHashMap是线程安全的,不会同步整个地图。 写入完成后,读取速度可能会非常快。

两者都是HashMap的同步版本,它们的核心function和内部结构有所不同。

ConcurrentHashMap由内部分段组成,可以从概念上看作独立的HashMap。 所有这些段可以在高并发执行中被单独的线程locking。 因此,multithreading可以从ConcurrentHashMap获取/放置键/值对,而不会相互阻塞/等待。 这是为了实现更高的吞吐量。

Collections.synchronizedMap() ,我们得到了一个HashMap的同步版本,并且以阻塞的方式访问它。 这意味着如果多个线程同时尝试访问synchronizedMap,它们将被允许以同步方式一次一个地获取/放置键值对。

ConcurrentHashMap使用更细粒度的locking机制(称为lock stripping来实现更高程度的共享访问。 由于这一点,它提供了更好的并发性可伸缩性

此外,为ConcurrentHashMap返回的迭代器是弱一致的,而不是由Synchronized HashMap使用的失败快速技术

我们可以通过使用ConcurrentHashMap和synchronizedHashmap来实现线程安全。 但是,如果你看看他们的架构,那么就会有很多不同。

  1. synchronisedHashmap

它将保持对象级别的locking。 所以如果你想执行任何操作,如put / get,那么你必须先获得锁。 同时,其他线程不允许执行任何操作。 所以一次只有一个线程可以对此进行操作。 所以等候时间会增加 与ConcurrentHashMap比较,可以说性能相对较低。

  1. 的ConcurrentHashMap

它将保持段级的locking。 它有16个段,默认情况下保持并发级别为16。 所以一次有16个线程可以在ConcurrentHashMap上运行。 而且,读取操作不需要locking。 所以任何数量的线程都可以对它执行get操作。

如果线程1想要在段2中执行put操作,并且线程2想要在段4上执行put操作,那么在这里它是允许的。 意思是说,16个线程一次可以对ConcurrentHashMap执行更新(put / delete)操作。

所以这里的等待时间会less一些。 因此,性能比同步的Hashmap要好。

SynchronizedMap上的方法保持对象上的locking,而在ConcurrentHashMap有一个“locking条带化”的概念,而locking是在内容的存储桶上进行的。 从而提高了可扩展性和性能。

ConcurrentHashMap:

1)这两个映射都是Map接口的线程安全实现。

2)在预期高并发的情况下,实现ConcurrentHashMap以获得更高的吞吐量。

3)对象级没有locking。

同步哈希映射:

1)每个方法都使用一个对象级锁来进行同步。

ConcurrentHashMap允许并发访问数据。 整个地图被分成几个部分。

读操作即。 get(Object key)即使在段级别也不同步。

但是写操作即。 remove(Object key), get(Object key)在段级别获取locking。 整个映射只有一部分被locking,其他线程仍然可以读取除locking之外的各个段的值。

另一方面, SynchronizedMap在对象级别获取locking。 所有线程都应等待当前线程,而不pipe操作如何(读/写)。