ConcurrentHashMap vs同步HashMap
在HashMap
和ConcurrentHashMap
上使用包装类SynchronizedMap
什么区别? 它只是能够修改HashMap
而迭代它( ConcurrentHashMap
)?
同步HashMap
:
-
每个方法都使用对象级别locking进行同步。 所以synchMap上的get和put方法获得一个锁。
-
locking整个集合是一个性能开销。 当一个线程持有锁时,其他线程不能使用该集合。
ConcurrentHashMap
是在JDK 5中引入的。
-
在对象级别没有locking,locking的粒度更加精细。 对于
ConcurrentHashMap
,锁可能位于hashmap存储桶级别。 -
较低级别locking的效果是,您可以使同步读取器和写入器不可能用于同步集合。 这导致更多的可扩展性。
-
如果一个线程试图修改而另一个线程正在迭代,则
ConcurrentHashMap
不会抛出ConcurrentModificationException
exception。
这篇文章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来实现线程安全。 但是,如果你看看他们的架构,那么就会有很多不同。
- synchronisedHashmap
它将保持对象级别的locking。 所以如果你想执行任何操作,如put / get,那么你必须先获得锁。 同时,其他线程不允许执行任何操作。 所以一次只有一个线程可以对此进行操作。 所以等候时间会增加 与ConcurrentHashMap比较,可以说性能相对较低。
- 的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操作如何(读/写)。