1. JDK1.7
⾸先将数据分为⼀段⼀段的存储,然后给每⼀段数据配⼀把锁,当⼀个线程占⽤锁访问其中⼀个段数据时,其他段的数据也能被其他线程访问。
ConcurrentHashMap
是由Segment
数组结构和HashEntry
数组结构组成。
Segment
实现了ReentrantLock
,所以Segment
是⼀种可重⼊锁,扮演锁的⻆⾊。HashEntry
⽤于存储键值对数据。
static class Segment<K,V> extends ReentrantLock implements Serializable {
}
⼀个ConcurrentHashMap
⾥包含⼀个Segment
数组。Segment
的结构和HashMap
类似,是⼀种数组和链表结构,⼀个Segment
包含⼀个HashEntry
数组,每个HashEntry
是⼀个链表结构的元素,每个Segment
守护着⼀个HashEntry
数组⾥的元素,当对 HashEntry
数组的数据进⾏修改时,必须⾸先获得对应的Segment
的锁。
2. JDK1.8
ConcurrentHashMap
取消了Segment
分段锁,采⽤CAS
和synchronized
来保证并发安全。数据结构跟HashMap1.8
的结构类似,数组+链表/红⿊⼆叉树。Java 8 在链表⻓度超过⼀定阈值(8)时将链表(寻址时间复杂度为O(N)
)转换为红⿊树(寻址时间复杂度为O(log(N))
)
synchronized
只锁定当前链表或红⿊⼆叉树的⾸节点,这样只要 hash 不冲突,就不会产⽣并发,效率⼜提升。
留言