coucurrentHashMap如何高效的实现线程安全的?

Java提供了不同层面的线程安全的支持,传统的集合框架内部,提供了同步包装,利用Collections可以生成,但是粒度都很粗,都是Synchronized的

后来并发包中提供所谓的线程安全容器类

例如ConcurrentHashMap CopyOnWriteArrayList

ArrayBlockingQueue SynchronousQueue.

ConcurrentHashMap本身也是在不断的演进的

早期的ConcurrentHashMap,实现基于的是

图片

分离锁,内部分段,存放了HashEntry的数组,每次只锁住对应的段,Segment的数量有所谓的concurrentcyLevel决定,默认是16

然后HashEntry内部使用了volatile的value来保证可见性,并且利用了不可变和Unsafe来进行改进操作

图片

对于put,通过哈希计算避免了哈希冲突,然后Segment进行相对应的put操作

图片

图片

ConcurrentHashMap获取再入锁,保证数据一致性,就是在Segment基于ReentrantLock

对于扩容,则是对于Segment进行扩容

对于更新,则是判断key是否数组里面,进行了重复的判断操作

后来在Java8就进行了改进

内部存储改进为HashMap结构非常相似

内部的Segment定义,只是为了保证序列化的兼容性

初始化的操作改了了lazy-load,避免了初始化开销

数据存储利用volatile进行可用性

使用CAS等操作,在特定场景进行无锁的操作

使用Unsage LongAddr等底层手段,进行极端情况的优化

图片

Key是final的,value的声明为volatile保证可见性

并发的put如何实现的

图片

初始化操作实现在initTable里面,里面利用了CAS尝试利用SizeCtl进行互斥,进行竞争性的初始化,就spin

图片

而里面的size操作,使用sumCount方法

图片

利用了近似AtomicLong的方式,进行了分段进行计数,最后进行求和

发表评论

邮箱地址不会被公开。 必填项已用*标注