我们直到?HashTable虽是线程安全的但是它锁住了整张hash表,所以性能很低,读读都互斥。那么ConcyrrentHashmap时如何在兼顾安全性的同时有实现高效性的呢?
- 首先是JDK1.7中ConcyrrentHashmap的实现原理。
相对于线程安全的Hashtable来说,ConcyrrentHashmap的性能更高,原因是什么呢?在JDK1.7中ConcyrrentHashmap的底层实现是Segement+哈希表。如何理解呢?见下图:
在初始化后变为16个Segement且无法更改,不可扩容(是Segement不可扩容,初始化后就会定死为16)扩容的是Segement对应的小哈希表。
ConcyrrentHashmap锁的是这16个Segement,它由hashtable的一把锁变为Segement的16把锁,锁的粒度更细,支持的并发数增加。线程1拿到的Segement1的锁不会影响线程2访问其他的Segement。
Segement是ReentrantLock的子类,使用Lock来保证线程安全
2.JDK1.8中ConcyrrentHashmap实现原理
在JDK1.8中ConcyrrentHashmap的底层由原来的**”Segement+哈希表“**变为
“哈希表+红黑树”,不多说,直接上图:
此时的Segment值保留结构,支持扩容,且此时的ConcyrrentHashmap锁的是哈希桶(哈希表中的具体的每个头结点)粒度更细了锁的个数会随着表的扩容而增加
后续会具体说明关于多线程以及线程安全的问题