使用包装类SynchronizedMap
在HashMap
和ConcurrentHashMap
上有何区别?仅仅是能否在迭代过程中修改HashMap
(ConcurrentHashMap
)吗?
使用包装类SynchronizedMap
在HashMap
和ConcurrentHashMap
上有何区别?仅仅是能否在迭代过程中修改HashMap
(ConcurrentHashMap
)吗?
同步的 HashMap
:
每个方法都使用 对象级锁
进行同步。因此,在synchMap上执行get和put方法时会获取锁。
锁定整个集合会导致性能开销。当一个线程持有锁时,其他线程无法使用该集合。
ConcurrentHashMap
在JDK 5中引入。
没有对象级别上的锁定,锁定的粒度更细。对于 ConcurrentHashMap
,锁可能在 哈希映射桶级别
上。
低级别锁定的效果是可以同时进行读取和写入,并发读写对于同步集合来说不可能。这使得其具有更高的可扩展性。
如果一个线程在迭代 ConcurrentHashMap
时另一个线程试图修改它,它不会抛出 ConcurrentModificationException
。
这篇文章 Java 7: HashMap vs ConcurrentHashMap 是一篇非常好的阅读材料。强烈推荐。
简短回答:
这两个地图都是实现了Map
接口的线程安全的实现。在需要高并发的情况下,ConcurrentHashMap
的实现可以提供更高的吞吐量。
Brian Goetz关于ConcurrentHashMap
背后的思想的文章是非常好的阅读材料。强烈推荐。
Map m = Collections.synchronizedMap(new HashMap(...));
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html - X-HuManConcurrentHashMap
是线程安全的,而不需要同步整个映射。读取操作非常快速,而写操作则使用锁进行。
我们可以通过使用ConcurrentHashMap和synchronizedHashmap来实现线程安全。但是,如果您查看它们的架构,差异很大。
它将在对象级别维护锁定。因此,如果您要执行任何操作(如put/get),则必须首先获取锁定。同时,不允许其他线程执行任何操作。因此,在同一时间内,只有一个线程可以对其进行操作。因此等待时间会增加。我们可以说,与ConcurrentHashMap相比,性能较低。
它将在段级别维护锁定。默认情况下,它有16个段并维护并发级别为16。因此,同时,16个线程可以在ConcurrentHashMap上进行操作。此外,读取操作不需要锁定。因此,任意数量的线程可以对其执行get操作。
如果thread1想在段2中执行put操作,而thread2想在段4中执行put操作,则允许在此处执行。这意味着,16个线程可以同时对ConcurrentHashMap执行更新(put/delete)操作。
因此,这里的等待时间会更少。因此,性能比synchronizedHashmap相对更好。
两者都是HashMap的同步版本,其核心功能和内部结构有所不同。
ConcurrentHashMap由内部段组成,可以概念化为独立的HashMap。在高并发执行中,所有这些段都可以由单独的线程锁定。因此,多个线程可以从ConcurrentHashMap获取/放置键值对,而无需阻止/等待彼此。这是为了更高的吞吐量。
而
Collections.synchronizedMap(),我们获得了一个同步版本的HashMap,并以阻塞方式访问它。这意味着如果多个线程尝试同时访问synchronizedMap,则它们将被允许以同步方式依次获取/放置键值对。
ConcurrentHashMap
使用更细粒度的锁机制,称为锁分离
,以允许更大程度的共享访问。因此,它提供了更好的并发性和可伸缩性。
此外,ConcurrentHashMap
返回的迭代器是弱一致性的,而不是Synchronized HashMap使用的快速失败技术。
SynchronizedMap
上的方法持有对象上的锁,而在 ConcurrentHashMap
中存在“锁分离”概念,其中锁定内容的桶。因此,ConcurrentHashMap
具有更好的可扩展性和性能。
ConcurrentHashMap :
1) 两个映射都是Map接口的线程安全实现。
2) ConcurrentHashMap 用于在期望高并发的情况下提供更高的吞吐量。
3) 对象级别没有锁定。
Synchronized Hash Map:
1) 每个方法都使用对象级别锁定进行同步。
一个简单的ConcurrentHashMap和Synchronized HashMap性能测试。测试流程是在一个线程中调用put
,并在三个线程上同时调用get
。正如@trshiv所说,当读取操作无需锁定时,ConcurrentHashMap具有更高的吞吐量和速度。结果是当操作次数超过10^7
时,ConcurrentHashMap比Synchronized HashMap快2x
。
Hashtable
和Synchronized HashMap
有什么不同? - roottravellerConcurrentHashMap
的size()
方法返回的结果可能已经过时。根据《Java并发编程实践》一书,size()
方法允许返回一个近似值而不是准确的计数。因此,应该谨慎使用这个方法。 - Andrii Lisun