ConcurrentHashMap 和 HaspMap比较:
1 、HashMap是线程不安全的,多线程环境中的put方法容易引起死循环,CPU利用率暴增到100%
2 、Hashtable是一个非常古老的类(都没有遵循驼峰命名)但它是一个线程安全的类,所有的操作都使用了synchronized,在整个哈希表上上了一把锁(相当于数据库中的表锁的概念),多线程的时候只有一个线程能够实现操作,其它线程都是阻塞状态,一个个的排序执行(多线程中,性能非常差)
2 、ConcurrentHaspMap中 大量的使用看volatile、final、CAS来减少锁的竞争,同时使用分段锁的方式,减小了锁的粒度
ConcurrentHashMap在JDK1.7和JDK1.8中实现有很大的区别
ConcurrentHashMap在JDK1.7的实现:数组+Segment+分段锁
ConcurrentHashMap内部是一个哈希表,同时每一个头结点(数组的多个单元)可以看做是一个Segment(我们的上锁的对象),这样每一个哈希表就被分成了很多的段(类似于行锁)只要不是同一个Segment中的数据,就能够实现多个线程的并发访问,从而实现效率的提高
ConcurrentHashMap在JDK1.8的实现:数组+链表+红黑树(Node节点)
这里要谈谈CAS(比较和交换),CAS是一种基于乐观锁的操作 ,CAS方法的操作数:
1、内存位置 (V)
2、预期值 (A)
3、新值 (B)
原理:内存位置上的值和预期值相同 , 则将内存的值更新为新值
JDK1.8使用Node<key, value>来替换了 Segment的概念, Node节点中的value和指向下一个节点的指针,都是使用了volatile类型,从而保证了数据内存的可见性(轻量级的线程安全),同时基本保证线程的安全性
<strong>class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
volatile V val;
volatile Node<K,V> next;
}
当我们的元素个数大于8 ,HashMap会将原来的链表O(N),转换成为 红黑树O(logN)来实现新能的提升,1.8中的锁的粒度进一步的减小