java并发编程--ConcurrentHashMap的并发

ConcurrentHashMap:ConcurrentHashMap 和 HashMap 思路是差不多的,但是因为它支持并发操作,所以要复杂一 些。整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“的 意思,所以很多地方都会将其描述为分段锁。ConcurrentHashMap 是一个 Segment 数组,Segment 通过继承 ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每 个 Segment 是线程安全的,也就实现了全局的线程安全。

java并发编程--ConcurrentHashMap的并发

不过在jdk8之后引入了红黑树,后面的结果有点变化:

java并发编程--ConcurrentHashMap的并发

 

HashTable:Hashtable 是遗留类,很多映射的常用功能与 HashMap 类似,不同的是它承自 Dictionary 类, 并且是线程安全的,任一时间只有一个线程能写 Hashtable,并发性不如 ConcurrentHashMap, 因为 ConcurrentHashMap 引入了分段锁。Hashtable 不建议在新代码中使用,不需要线程安全 的场合可以用 HashMap 替换,需要线程安全的场合可以用 ConcurrentHashMap 替换。

 

不过在这里还是要重点讲一下ConcurrentHashMap:

ConcurrentHashMap 的优点:

1.减小锁粒度

我们解决并发问题主要是get和set方法,如果我们对整个 HashMap 加锁,可以得到线程安全的对象,但是加锁粒度太大。通过segment来进行锁分段,可以很好的减少锁粒度,因此Segment 的大小也被 称为 ConcurrentHashMap 的并发度。

2.分段锁

ConcurrentHashMap,它内部通过segment细分了若干个小的 HashMap,称之为段(Segment)。如果需要在 ConcurrentHashMap 中添加一个新的表项,并不是将整个 HashMap 加锁,而是首先根据 hashcode 得到该表项应该存放在哪个段中,然后对该段加锁,并完成 put 操作。在多线程 环境中,如果多个线程同时进行 put操作,只要被加入的表项不存放在同一个段中,则线程间可以 做到真正的并行。

3.ConcurrentHashMap 是由 Segment 数组结构和 HashEntry 数组结构组成

ConcurrentHashMap 是由 Segment 数组结构和 HashEntry 数组结构组成。Segment 是一种可 重入锁 ReentrantLock,在 ConcurrentHashMap 里扮演锁的角色,HashEntry 则用于存储键值 对数据。一个 ConcurrentHashMap 里包含一个 Segment 数组,Segment 的结构和 HashMap 类似,是一种数组和链表结构, 一个 Segment 里包含一个 HashEntry 数组,每个 HashEntry 是 一个链表结构的元素, 每个 Segment 守护一个 HashEntry 数组里的元素,当对 HashEntry 数组的 数据进行修改时,必须首先获得它对应的 Segment 锁。

java并发编程--ConcurrentHashMap的并发