分布式缓存
CDN
反向代理
本地
分布式
ConcurrentHashMap 解决HashMap并发死循环
hashmap并发死循环原理
前提:线程1进行到了扩容后的第一步,记录当前节点为3,下一个为7;线程2扩容完并重新散列完。接下来线程1继续工作,e=7,读取线程2重新散列完的map,得到next=3;接下来把3用头插法塞到最前面,同时记录next=7,fine,开始死循环。
死锁和死循环:死锁是因为无法获得资源陷入僵持,死循环是一直在跑,但跑不出去。
JDK8中ConcurrentHashMap参考了JDK8 HashMap的实现,采用了数组+链表+红黑树的实现方式来设计。
红黑树
看完教程后可以直接理解具体操作
用五条定义来近似平衡树,并不追求完美平衡,以此换速度。用红黑结点将2-3-4树转化为二叉树,也表达了一种父子关系。插入时将插入结点 视作红色节点,避免红-红左倾、右倾或单链结构的产生;删除时进行染色,通过转化为3/4结点的方式避免删除2结点。
JDK1.7中ConcurrentHashMap分为好几个segment,每个segment加锁。segment中再次hash找到entry。内部大量采用CAS操作,这里我简要介绍下CAS。CAS是compare and swap的缩写,即我们所说的比较交换。cas是一种基于锁的操作,而且是乐观锁。
悲观锁
访问加锁,一个线程访问完另一个再访问。
乐观锁
先获取一个值,操作时比较一下获取的值和当前值是否相同,如果相同,进行操作。
JDK8中彻底放弃了Segment转而采用的是Node,其设计思想也不再是JDK1.7中的分段锁思想。
Node:保存key,value及key的hash值的数据结构。其中value和next都用volatile修饰,保证并发的可见性。
volatile关键字
相对加锁较为轻量级,有两个特点:一是更新时对内存可见,即更新时强制将线程本地缓存刷新到主内存中,并使得其他线程缓存无效;二是防止编译器对指令重排。该关键字不适合复合操作,如ans++,即不保证原子性。
部分源码分析:深入浅出ConcurrentHashMap1.8
明天看redis 2022/3/4
标签:ConcurrentHashMap,加锁,结点,JDK8,线程,Wandering,死循环 From: https://www.cnblogs.com/capterlliar/p/17178746.html