我有一个映射,这是由几个线程并发修改。
在Java API中似乎有三种不同的同步Map实现:
哈希表
collections . synchronizedmap(地图)
ConcurrentHashMap
根据我的理解,Hashtable是一个旧的实现(扩展了过时的Dictionary类),后来为了适应Map接口而进行了调整。虽然它是同步的,但它似乎有严重的可伸缩性问题,不推荐用于新项目。
那另外两个呢?Collections.synchronizedMap(Map)和ConcurrentHashMaps返回的Map之间有什么区别?哪一种适合哪种情况?
两者之间的主要区别是ConcurrentHashMap将只锁定正在更新的部分数据,而其他部分数据可以由其他线程访问。但是,Collections.synchronizedMap()将在更新时锁定所有数据,其他线程只能在释放锁时访问数据。如果更新操作较多,读操作相对较少,则选择ConcurrentHashMap。
Also one other difference is that ConcurrentHashMap will not preserve the order of elements in the Map passed in. It is similar to HashMap when storing data. There is no guarantee that the element order is preserved. While Collections.synchronizedMap() will preserve the elements order of the Map passed in. For example, if you pass a TreeMap to ConcurrentHashMap, the elements order in the ConcurrentHashMap may not be the same as the order in the TreeMap, but Collections.synchronizedMap() will preserve the order.
此外,ConcurrentHashMap可以保证当一个线程更新映射而另一个线程遍历从映射中获得的迭代器时,不会抛出ConcurrentModificationException。但是,Collections.synchronizedMap()在此上不被保证。
有一篇文章展示了这两者的区别,还有ConcurrentSkipListMap。
同步地图:
Synchronized Map与Hashtable也没有太大区别,在并发Java程序中提供了类似的性能。哈希表和SynchronizedMap之间的唯一区别是SynchronizedMap不是遗留的,您可以使用Collections.synchronizedMap()方法包装任何Map来创建它的同步版本。
ConcurrentHashMap:
ConcurrentHashMap类提供了标准HashMap的并发版本。这是对Collections类中提供的synchronizedMap功能的改进。
与哈希表和同步映射不同,它从不锁定整个映射,而是将映射划分为段,并在这些段上锁定。如果读取线程的数量大于写入线程的数量,它的性能会更好。
默认情况下,ConcurrentHashMap被划分为16个区域,并应用了锁。这个默认值可以在初始化ConcurrentHashMap实例时设置。当在特定的段中设置数据时,将获得该段的锁。这意味着如果两个更新分别影响不同的存储桶,那么它们仍然可以同时安全执行,从而最大限度地减少锁争用,从而最大化性能。
ConcurrentHashMap不会抛出ConcurrentModificationException异常
如果一个线程试图修改它,而另一个线程正在遍历它,ConcurrentHashMap不会抛出ConcurrentModificationException
synchronizedmap和ConcurrentHashMap的区别
collections . synchronnizedmap (HashMap)将返回一个几乎相当于Hashtable的集合,其中Map上的每个修改操作都锁定在Map对象上,而对于ConcurrentHashMap,线程安全是通过根据并发级别将整个Map划分为不同的分区,只锁定特定的部分而不是锁定整个Map来实现的。
ConcurrentHashMap不允许空键或空值,而synchronized HashMap允许一个空键。
类似的链接
Link1
Link2
性能比较
我们可以通过使用ConcurrentHashMap和synchronisedHashmap和Hashtable来实现线程安全。但如果你看看他们的架构,就会发现有很多不同。
synchronisedHashmap和Hashtable
两者都将在对象级别上维护锁。所以如果你想执行任何操作,比如put/get,那么你必须先获得锁。同时,其他线程不允许执行任何操作。所以在同一时间,只有一个线程可以操作这个。所以这里的等待时间会增加。我们可以说,与ConcurrentHashMap相比,性能相对较低。
ConcurrentHashMap
It will maintain the lock at segment level. It has 16 segments and maintains the concurrency level as 16 by default. So at a time, 16 threads can be able to operate on ConcurrentHashMap. Moreover, read operation doesn't require a lock. So any number of threads can perform a get operation on it.
If thread1 wants to perform put operation in segment 2 and thread2 wants to perform put operation on segment 4 then it is allowed here. Means, 16 threads can perform update(put/delete) operation on ConcurrentHashMap at a time.
So that the waiting time will be less here. Hence the performance is relatively better than synchronisedHashmap and Hashtable.