ConcurrentHashMap 跟 HashMap 一样:数组+链表+红黑树的方式。
问:ConcurrentHashMap 的源码是如何实现线程安全的?
答:它主要是通过 CAS+volatile 或者是 synchronized 的方法来实现的,保证线程安全。并且也缩小了锁的粒度,查询性能也到了进一步的提升。
首先会判断容器是否为空:
1、如果容器为空,就会使用volatile+CAS来初始化。
2、如果容器不为空,就会根据存储的元素计算该位置是否为空。
1)如果根据存储元素的计算结果为空,就会利用CAS来设计该节点。
2)如果根据存储元素的计算结果不为空,就会使用synchronized加锁来进行实现。然后去遍历桶中的数据, 并且替换或新增节点到桶中。最后判断是否有必要转为红黑树。这样就保证了并发访问的线程安全。
总结:
如果把上面的执行用一句话来归纳的话,就相当于ConcurrentHashMap通过对头节点加锁来保证线程安全,这样设计的好处是使得锁的粒度相比Segment来说更小了,发生hash冲突和加锁的频率也更低了,而在并发场景下操作性能也提高了。而且当数据量比较大的时候,查询性能也得到了进一步的提升。
不会进行全局锁定:与Hashtable等旧版哈希表不同,ConcurrentHashMap的读操作不需要获取锁,只有在写操作时才需要进行锁定。这样可以允许多个线程同时读取数据,提高并发性能。