atomicReference 的使用和AtomicStampedReference 解决ABA的问题
不忘初心,方得始终
正文
atomicReference 可以保证对象的原子操作.

public static void main(String[] args) { AtomicReference<Simple> atomic = new AtomicReference<>(new Simple("xiaodao",23)); System.out.println(atomic.get()); boolean result = atomic.compareAndSet(atomic.get(), new Simple("bbb", 90)); System.out.println(result); } static class Simple{ private String name; private int age; public Simple(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
CAS
cas带来的好处
1.可见性
2.有序性
3.原子性
volatile修饰的变量,保证前俩者
CAS算法,也就是cpu级别的同步指令,相当于乐观锁,它可以探测到其他线程对共享数据的变化情况\
cas带来一个ABA问题
什么是ABA呢?
就是俩个线程同事操作,有可能有一个线程已经处理结束,那么第一个线程中间又一次fail操作,会在这个结果上在进行计算
t1 t2
A A->B->A
A->C
那我们来看下维基百科上面的形象描述:
你拿着一个装满钱的手提箱在飞机场,此时过来了一个火辣性感的美女,然后她很暖昧地挑逗着你,并趁你不注意的时候,把用一个一模一样的手提箱和你那装满钱的箱子调了个包,然后就离开了,你看到你的手提箱还在那,于是就提着手提箱去赶飞机去了。
如何解决ABA的问题呢?
在数据库中是使用乐观锁来解决的这问题version一直在变化
在多线程中我们有一个类 AtomicStampedReference可以这样解决
public class AtomicStampedReferenceTest { private static AtomicStampedReference<Integer> atomic = new AtomicStampedReference<>(100,0); public static void main(String[] args) { new Thread(()->{ try { TimeUnit.SECONDS.sleep(1); //和乐观相似,第一个stamp相当于 version 每次加1 如果别的线程修改过就是1了.第一个线程0就对比不成功 boolean sucess = atomic.compareAndSet(100,101,atomic.getStamp(),atomic.getStamp()+1); System.out.println(sucess); sucess = atomic.compareAndSet(101,100,atomic.getStamp(),atomic.getStamp()+1); System.out.println(sucess); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); new Thread(()->{ try { int stamp = atomic.getStamp(); System.out.println("before: "+stamp);//这里获取到的stamp是1 TimeUnit.SECONDS.sleep(2); int stamp1 = atomic.getStamp(); System.out.println("第一个线程的 stamp "+ stamp1);//这里第一个线程的stamp已经变成2 了 //和乐观相似,第一个stamp相当于 version 每次加1 如果别的线程修改过就是1了.第一个线程0就对比不成功 boolean b = atomic.compareAndSet(100, 101, stamp, stamp + 1); System.out.println("2线程= "+b); atomic.compareAndSet(101,100,stamp,stamp+1); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } }
源码:
我=copy了一点 也不算太复杂,就是初始化的时候放进入一个值,和一个版本号,
然后进行compareAndSet 的话,就是比对预期的值和当前的值,还有预期的版本号和当前的版本号
private static class Pair<T> { final T reference; final int stamp; private Pair(T reference, int stamp) { this.reference = reference; this.stamp = stamp; } static <T> Pair<T> of(T reference, int stamp) { return new Pair<T>(reference, stamp); } } private volatile Pair<V> pair; /** * Creates a new {@code AtomicStampedReference} with the given * initial values. * * @param initialRef the initial reference * @param initialStamp the initial stamp */ public AtomicStampedReference(V initialRef, int initialStamp) { pair = Pair.of(initialRef, initialStamp); }
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
一起交流进步.扫描下方QQ二维码即可

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义