1、ConcurrentHashMap的锁分段技术
分段锁,分成segment,给对应的segment加锁。跟Hashtable的全段加锁区分
2、get没有加锁的话,ConcurrentHashMap是如何保证读到的数据不是脏数据的呢?
答:Java提供了volatile关键字来保证可见性、有序性。但不保证原子性。
volatile关键字对于基本类型的修改可以在随后对多个线程的读保持一致,但是对于引用类型如数组,实体bean,仅仅保证引用的可见性,但并不保证引用内容的可见性。
禁止进行指令重排序。
*
总结下来:
*
第一:使用volatile关键字会强制将修改的值立即写入主存;
*
第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);
*
第三:由于线程1的工作内存中缓存变量的缓存行无效,所以线程1再次读取变量的值时会去主存读取。
*
3、用volatile修饰的Node
get操作可以无锁是由于Node的元素val和指针next是用volatile修饰的,在多线程环境下线程A修改因为hash冲突修改结点的val或者新增节点的时候是对线程B可见的。
总结
*
在1.8中ConcurrentHashMap的get操作全程不需要加锁,这也是它比其他并发集合比如hashtable、用Collections.synchronizedMap()包装的hashmap;安全效率高的原因之一。
*
get操作全程不需要加锁是因为Node的成员val是用volatile修饰的和数组用volatile修饰没有关系。
*
数组用volatile修饰主要是保证在数组扩容的时候保证可见性。