专注Java教育14年 全国咨询/投诉热线:444-1124-454
赢咖4LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 Java中cas实现原理

Java中cas实现原理

更新时间:2022-09-28 08:55:11 来源:赢咖4 浏览596次

java提供了三个CAS操作不安全:

compareAndSwapLong compareAndSwapObject compareAndSwapInt () () ()

//Parameter meaning: object, attribute memory offset, attribute expected value, attribute update value
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

抵消:对象在内存中包含对象头和对象实例数据,和对象头占8个字节。对于64位的操作系统,压缩指针占4个字节,所以我们通常说的对象头占12个字节;例如,测试对象,x的偏置是头的对象,也就是说,12个字节,和y的抵消是16

cas操作修改测试类的变量x。

public class CASTest {
    public static void main(String[] args) {
        Test test = new Test();
        Unsafe unsafe = UnsafeFactory.getUnsafe();
        long xOffset = UnsafeFactory.getFieldOffset(unsafe, Test.class, "x");
        System.out.println(xOffset); //12
        long yOffset = UnsafeFactory.getFieldOffset(unsafe, Test.class, "y");
        System.out.println(yOffset); //16
        unsafe.compareAndSwapInt(test, xOffset, 0, 1);
        System.out.println(test.x);
    }    
    static class Test {
        int x;
        int y;
    }
}

能保证原子性,但不能保证秩序和可见性。因此,一般来说,可以用于挥发性,以确保线程安全。底层最后执行CAS指令(原子操作修改变量值)和比较期望值与实际值在内存中。如果比较结果相等,返回旧值(期望值),表明CAS操作成功。如果他们是不平等的,在内存返回实际值,表明CAS操作失败。

CAS实现线程安全的操作

public class CASTest {
    private static int sum = 0;
    private static CASLock casLock = new CASLock();
    public static void main(String[] args) throws InterruptedException {
        for (int i=0; i<10; i++) {
            new Thread(() -> {
                for (;;) {
                    if (casLock.getState() == 0 && casLock.cas()) {
                        try {
                            for (int j = 0; j < 10000; j++) {
                                sum++;
                            }
                        } finally {
                            casLock.setState(0);
                        }
                        break;
                    }
                }
            }).start();
        }
        Thread.sleep(2000);
        System.out.println(sum);
    }
}
public class CASLock {
    private volatile int state = 0;
    private static final Unsafe UNSAFE;
    private static final long OFFSET;
    static {
        UNSAFE = UnsafeFactory.getUnsafe();
        OFFSET = UnsafeFactory.getFieldOffset(UNSAFE, CASLock.class, "state");
    }    
    public int getState() {
        return state;
    }
    public void setState(int state) {
        this.state = state;
    }
    public boolean cas() {
        return UNSAFE.compareAndSwapInt(this, OFFSET, 0, 1);
    }
}

原子在jdk类juc下包通过cas是线程安全的。

LongAdder和DoubleAdder原则

在高并发性下,CAS操作将有大量的线程旋转,导致浪费线程资源。为了提高执行效率,V值分为多个变量。多个线程执行CAS操作同时在自己的变量。所有线程完成后执行,所有变量都是积累和统计。它的想法是类似于统计jdk8 ConcurrentHashMap的元素的数量。LongAdder DoubleAdder也实现这个想法。LongAdder定义了基本变量和单元数组变量,初始化并积累单元阵列通过散列,最后积累基础和单元阵列的所有数字的结果。

以上就是关于“Java中cas实现原理”的介绍, 大家如果想了解更多相关知识,不妨来关注一下赢咖4的Java赢咖4在线学习,里面的课程内容从入门到精通,细致全面,适合没有基础的小伙伴学习,希望对大家能够有所帮助。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>