Java
java.util
Arrays
HashSet
TreeSet
Deque
ArrayDeque
ArrayList
LinkedBlockingDeque
Map
HashMap
HashTable
TreeMap
LinkedHashMap
ComputeIfAbsent 在jdk8下的死锁场景
synchronized的锁升级过程
Volatile 关键字
redis 中的Lua脚本
AQS - 从干饭角度解析
ConcurrentHashMap
本文档使用 MrDoc 发布
-
+
首页
ConcurrentHashMap
## 分段加锁 ``` // ConcurrentHashMap的put方法直接就是调用的类中的putVal方法,所以我这里就直接贴出来putVal方法了 final V putVal(K key, V value, boolean onlyIfAbsent) { // key和value都不允许为null,否则会报错 if (key == null || value == null) throw new NullPointerException(); // 计算hash值 int hash = spread(key.hashCode()); // 当前链表中元素的个数 int binCount = 0; // table就是底层的数组 for (Node<K,V>[] tab = table;;) { Node<K,V> f; int n, i, fh; // 判断数组是否为空 if (tab == null || (n = tab.length) == 0) // 初始化数组,这里只有一个线程能进行初始化数组的操作 tab = initTable(); // 判断要put的元素的位置在数组中是为null,如果为null的话,说明当前位置没有值,不会发生hash冲突 else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { // 使用CAS操作将元素加入数组中,这样即使多个线程进入这个判断,也只有一个线程能put成功,失败的线程继续循环,保证了并发安全 if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null))) break; // no lock when adding to empty bin } // 扩容相关判断 else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); // 如果进入了这个else判断的话,那么说明发生了hash冲突,需要使用链表或者红黑树来处理 else { V oldVal = null; // 这里锁住的f在上面的代码中赋过值了,就是这句f = tabAt(tab, i = (n - 1) & hash) // 所以这里锁住的是发生hash冲突的一个Node节点,只是数组中的一个元素而已,而不是锁住了整个数组 synchronized (f) { if (tabAt(tab, i) == f) { if (fh >= 0) { binCount = 1; for (Node<K,V> e = f;; ++binCount) { K ek; // 如果key值一样的话,就使用新的value覆盖旧的value if (e.hash == hash && ((ek = e.key) == key || (ek != null && key.equals(ek)))) { oldVal = e.val; if (!onlyIfAbsent) e.val = value; break; } Node<K,V> pred = e; // 如果key不同的话,e一开始其实就是f,将新的元素使用链表的形式挂载在之前的元素后 if ((e = e.next) == null) { pred.next = new Node<K,V>(hash, key, value, null); break; } } } // 转化为红黑树之后,下次再有hash冲突的话,就直接将元素加入到红黑树中 else if (f instanceof TreeBin) { Node<K,V> p; binCount = 2; if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, value)) != null) { oldVal = p.val; if (!onlyIfAbsent) p.val = value; } } } } if (binCount != 0) { // 如果binCount的值大于等于8的话,就将链表转化为红黑树 if (binCount >= TREEIFY_THRESHOLD) treeifyBin(tab, i); if (oldVal != null) return oldVal; break; } } } addCount(1L, binCount); return null; } ``` https://blog.csdn.net/LO_YUN/article/details/106358362 ## JDK8下的死锁场景 [ComputeIfAbsent 在jdk8下的死锁场景](https://www.coldsmog.cn/project-5/doc-196/)
寒烟濡雨
2024年3月8日 11:02
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码