我结合上一篇的HashMap再来复习一下ConcurrentHashMap
ConcurrentHashMap和HashMap相比较最大的不同是线程安全
至于为什么线程安全在JDK1.7和Jdk1.8是不一样的
我们来看看1.7版本
1.它的底层数据结构还是数组加上链表 ,HashEntry为链表的结点
2.它主要采用了segment分段锁技术,在多线程并发操作的时候。对同一个segment进行同步加锁,保证数据的安全。这样就可以基于不同的segment进行并发写操作。这样就提升了效率我们通过和HashTable相比较来更深刻的理解为什么这样更有效率,以及为什么ConcurrentHashMap的效率比同是多线程的HashTable更高,因为HashTable将整个put/get,操作都锁上了,这就导致锁上了整个HashTable对象,这样的话效率就很低,比如 在 有些不同的indx值进行写操作,ConcurrentHashMap可以可能进行并行或者并发来处理,效率更高,而HashTable只能同步互斥来处理,总的来说我们细化了锁,在等下我们提到jdk1.8版本的时候我还会再说说 ,segment的缺点,以及其他的补充。
3.同步的实现方式也就是我们上面提到的分段锁,是继承了Reentrant锁机制,(segment继承自ReentrantLock)。具体来说对于同一个segment的操作是ReentrantLock.lock()/unlock()进行线程间的同步。
4.和HashMap一样。同样存在hash冲突,链表查询效率低的问题
我们来看看1.8
**1.**底层的数据结构和1.8版本的HashMap一样为 数组+链表+红黑树.
**2.**支持多线程的并发操作。实现原理是:CAS+synchronized保证并更新
**3.**put方法存放元素时,通过key对象的hashcode计算数组的索引,如果没有Node,
则使用CAS尝试插入元素,失败则无条件自旋直到插入成功;如果存在Node,则使用synchronized锁住该元素(链表/红黑树的头节点),在执行插入操作
1.7和1.8的共同点
1.键,值迭代器为弱一致性迭代器 fail -safe迭代器 ,创建迭代器之后可以对元素进行更新,
2.读操作没有加锁,value是volatie修饰的,保证了可见性,所以是安全的
3.读写分离可以提高效率:多线程对不通过的Node/Segment的插入/删除可以并发,并行执行,读操作都是无锁操作,可以并发并行执行