Java JUC并发之原子引用
二十、原子引用
解决ABA问题 => 引入原子引用 对应思想:乐观锁
原子引用类 AtomicStampedReference<>(initialRef , initialStamp) 带版本号的原子操作!
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);
如果泛型是一个包装类,要注意对象的引用问题
注意:
Integer 使用了对象缓存机制,默认范围是 -128 - 127,超过范围会在堆中 new 一个新的对象;推荐使用静态工厂方法 valueOf获取对象实例,而不是 new!
因为 valueOf使用缓存,而 new 一定会创建新的对象,分配新的空间!
package com.liu.cas;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
public class CASDemo {
// CAS compareAndSet : 比较并交换
public static void main(String[] args) {
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);
new Thread(()->{
int stamp = atomicStampedReference.getStamp(); // 获得版本号
System.out.println("a1 ==> " + stamp);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 2,
atomicStampedReference.getStamp(),
atomicStampedReference.getStamp() + 1));
System.out.println("a2 ==> " + atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(2, 1,
atomicStampedReference.getStamp(),
atomicStampedReference.getStamp() + 1));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("a3 ==> " + atomicStampedReference.getStamp());
},"a").start();
new Thread(()->{
int stamp = atomicStampedReference.getStamp(); // 获得版本号
System.out.println("b1 ==> " + stamp);
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 6,
stamp,
stamp+1));
System.out.println("b2 ==> " + atomicStampedReference.getStamp());
},"b").start();
}
}
测试结果:
b2预期得到的版本号为 2,但实际上线程A中的修改操作让版本号变为了 3,线程B此时通过版本号检查发现线程A中出现了ABA问题,因此b2的CAS操作无法完成,返回了false。
本文来自博客园,作者:{夕立君},转载请注明原文链接:https://www.cnblogs.com/xili-sanriyue/p/15025585.html