如何基于当前值的Predicate原子性地条件更新AtomicReference?
基于AtomicReference实现条件性原子更新
我们可以通过自定义扩展AtomicReference的方式,实现你需要的conditionallyUpdate方法,满足基于当前值判断(如空值、过期)的原子更新需求,并发场景下保证操作的原子性,且其他线程在操作执行期间仍能看到原有值。
自定义增强型AtomicReference实现
封装一个EnhancedAtomicReference类,实现目标方法:
import java.util.function.UnaryOperator; import java.util.concurrent.atomic.AtomicReference; public class EnhancedAtomicReference<V> extends AtomicReference<V> { /** * 根据函数结果更新值,仅当函数返回非null时执行更新。 * 函数的入参为当前引用的实际值。 * 方法执行期间,并发调用的线程仍会看到当前的原有值。 * * @param function 接收当前值、返回新值的函数;返回null则不执行更新 * @return 更新后的最终值(可能是原有值,也可能是新值) */ public V conditionallyUpdate(UnaryOperator<V> function) { while (true) { V current = get(); V newValue = function.apply(current); // 函数返回null,直接返回当前值,不更新 if (newValue == null) { return current; } // CAS尝试更新,成功则返回新值,失败则重试 if (compareAndSet(current, newValue)) { return newValue; } } } }
使用示例
按照需求实现获取非过期值的方法:
public class ExampleUsage { private final EnhancedAtomicReference<Value> myAtomicRef = new EnhancedAtomicReference<>(); public Value getNonExpiredValue() { return myAtomicRef.conditionallyUpdate(existingVal -> { if (existingVal == null || existingVal.isExpired()) { return getNewVal(); } return null; // 无需更新,保留原有值 }); } // 模拟获取新值的方法 private Value getNewVal() { return new Value(); } // 模拟带过期判断的Value类 static class Value { public boolean isExpired() { // 此处实现过期判断逻辑 return false; } } }
实现说明
- 该方法通过CAS循环保证原子性:每次循环获取当前值,计算新值后尝试更新,若更新失败(说明有其他线程修改了值)则重试,直到成功或无需更新。
- 当函数返回null时,直接返回当前值,跳过更新操作,符合"原有值无需修改时不操作"的需求。
- 这个逻辑和ConcurrentMap的
compute方法类似,但专门针对单个原子引用场景,更轻量化。
内容的提问来源于stack exchange,提问作者peterh
相关产品推荐
相关产品推荐

