computeifpresent 在 concurrenthashmap 中实现指定 key 存在时的原子性更新:仅锁目标桶的首节点或树根,查到 key 且 value 非 null 才执行函数,返回 null 则删除,否则替换值,全程线程安全。

computeIfPresent 在 ConcurrentHashMap 中通过分段锁(JDK 8+ 改为 CAS + synchronized 细粒度加锁)和不可变性保障,实现对**指定 key 存在时的原子性更新**,不阻塞其他 key 的读写。
只锁目标 bin(桶),不影响其他 key
ConcurrentHashMap 不对整个 map 加锁。当调用 computeIfPresent(key, remappingFunction) 时:
- 先定位 key 所在的哈希桶(table[index])
- 若桶首节点是普通 Node,则用 synchronized 锁住该 Node 对象(不是整个 table)
- 若桶是红黑树,则锁住树的根节点(TreeBin)
- 锁范围极小,仅限当前 key 所在的链表/树结构,其他桶可并发操作
先查后算,全程原子判断
方法内部严格按顺序执行,无竞态窗口:
- 获取桶并加锁后,遍历链表或树查找 key 对应的 Entry
- 若 key 不存在(或值为 null),直接返回 null,不调用函数
- 若 key 存在且 value 非 null,才执行 remappingFunction(oldValue)
- 函数返回 null → 删除该 key;否则用新值替换旧值(仍复用原 Node,仅改 value 字段)
函数执行期间持有锁,避免中间态暴露
remappingFunction 是在同步块内调用的,这意味着:
- 其他线程无法在此期间修改该 key 对应的 value
- 即使函数耗时较长,也不会导致“读到半更新状态”——因为旧值未被覆盖前,外部始终看到原值
- 但要注意:函数本身应尽量轻量、无副作用、不依赖全局状态,否则会拖慢并发性能
与 compute、merge 等方法的区别要点
computeIfPresent 的语义限定更严格:
- 只在 key 存在且 value != null 时触发更新;key 不存在或 value 为 null 都不执行函数
- 不涉及插入逻辑(不像 compute 可能 putIfAbsent)
- 比 replace(key, oldValue, newValue) 更灵活——支持基于旧值计算新值,且天然线程安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











