CAS
Compare And Swap(比较并交换),涉及并发算法时常用到的一种技术。 java.util.concurrent.atomic 包下的原子操作类都是基于 CAS 实现的。
现在市面上的处理器基本都支持 CAS,只不过不同的厂家的实现不一样。
CAS 有三个操作数:内存值 V、旧的预期值 A、要修改的值 B,当且仅当预期值 A 和内存值 V 相同时,将内存值修改为 B 并返回 true,否则什么都不做并返回 false。
Java 中的 sun.misc.Unsafe 提供了 CAS 机制
Unsafe
Java 无法直接访问底层操作系统,只能通过本地(native)方法来访问。不过尽管如此,JVM 还是开了一个后门,JDK 中有一个类 Unsafe,它提供了硬件级别的原子操作。比如说获取某个属性在内存中的位置,修改对象的字段值。
但是 并没有办法
直接使用它们,JDK API 文档也没有提供任何关于这个类的方法的解释。对于 Unsafe 类的使用是受限制的。
那么我们怎么样来使用呢?
示例代码
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/**
* 使用CAS方式进行i++
* @author ldan
*
*/
public class CounterUnsafe {
int i = 0;
//Unsafe工具非常强大 ,可以去修改应用类型的值,可以修改对象的属性,可以修改数组 等等
private static Unsafe unsafe = null;
//代表了要修改的字段 是一个偏移量
private static long valueOffset;
static{
//官方不建议直接使用
//unsafe = Unsafe.getUnsafe();
//利用反射原理进行使用
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
//指定要修改的字段
Field iField = CounterUnsafe.class.getDeclaredField("i");
valueOffset = unsafe.objectFieldOffset(iField);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
void add(){
//i++不是原子性的
//i++;
//原子性的i++
while (true){//只有操作成功才return
if(unsafe.compareAndSwapInt(this, valueOffset, i, i+1))
return;
}
}
public static void main(String[] args) {
}
}
CAS 存在的问题
- 仅针对单个变量的操作,不能用于多个变量来实现原子操作。
- CAS 自旋的实现,可能让所有线程都出于高频运行,争抢 CPU 执行时间的状态。如果操作长时间不成功,会带来很大的 CPU 资源消耗。
- ABA 问题。(无法体现出数据的变动)
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于