JDK1.8以前,多个数组,分段加锁,一个数组一个锁
JDK1.8以后,优化细粒度,一个数组,每个元素进行CAS,如果失败就说明有线程操作,此时synchronized对数组元素加锁,链表+红黑树处理,对数组每个元素加锁
多线程要访问同一个数据,synchronized加锁,CAS去进行安全的累加,去实现多线程场景下的安全更新一个数据的效果,如果多个线程同时读写一个HashMap,就会大大影响性能
HashMap底层是一个大的数组
HashMap map = HashMap():
synchronized(map){
map.put(key,value);
}
多个线程执行put操作,但是只有一个线程可以获取到锁操作数据,比如线程1要put的位置是数组[1],线程2要put的位置是数组[2],由于对整个map加锁,则大大的影响性能明显不好,数组里有很多的元素,除非对同一个元素执行put操作,此时需要多线程进行同步操作
JDK并发包推出ConcurrentHashMap,默认实现了线程安全性
ConcurrentHashMap加锁原理:
-
JDK1.7以及之前的版本里,分段加锁,将数组拆分为多个数组,[数组]、[数组2]、[数组3] -->每个数组对应一个锁。多个数组操作,线程1要put的位置是数组1[2],线程2要put的位置是数组2[11]
-
JDK1.8以及之后,做了优化及改进,锁粒度的优化
[ 一个大的数组],数组里每个元素进行put操作,都有一个不同的锁,刚开始进行put 的时候,如果两个线程都是在数组[10]位置进行put,这个时候,对数组[10]这个位置进行put的时候,采取的是CAS的策略
同一时间,只有一个线程能成功执行这个CAS,刚开始先获取一下数组[10]这个位置的值,然后执行CAS,同时间,其他的线程执行CAS,都会失败
分段加锁,通过对数组每个元素执行CAS的策略,如果很多线程对数组里不同的元素执行put,那么互相不影响;如果其他线程执行失败,就需要在这个数组位置基于链表+红黑树来进行处理 ,synchronized( 数组[xx])加锁,基于链表或红黑树基础在这个位置插进去自己的数据