ConcurrrentHashMap
ConcurrentHashMap 使用锁分离技术来保证在多线程下的性能。它每次锁住一个桶,默认将 hash 表分为 16 个桶,诸如put和remove 等常用操作只锁当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有 16 个写线程执行,并发性能的提升是显而易见的。锁的粒度更小,并发程度更高。
读操作不加锁,非常快。由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。
ConcurrrentHashMap 使用一种不同的迭代方式。它不会抛出ConcurrentModificationException,即使一个线程在遍历的同时,另一个线程尝试进行修改。
Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap 允许多个修改操作并发进行,其关键在于使用了锁分离技术。有些方法需要跨桶,比如size()和containsValue(),它们可能需要锁定整个表而不仅仅是某个桶,这需要按顺序锁定所有桶,操作完毕后,又按顺序释放所有桶的锁。
段内扩容,段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容。插入前检测需不需要扩容,有效避免无效扩容。
SynchronizedHashMap
接下来主要说一下Collections类里的静态方法synchronizedMap(),入参有一个,需实现map接口。
同步整个对象,会极大降低性能。SynchronizedMap 每一次的读写操作都锁住整张表以保证线程安全,对读写加独占锁相当于同一时间内只允许至多一个线程操作整个Map,而其它线程必须等待,吞吐量和性能必然打折扣。
它有可能造成资源冲突(某些线程等待较长时间)。
SynchronizedHashMap会返回Iterator,当遍历时进行修改会抛出异常。