和Java源码谈恋爱

JDK源码分析之CAS

2019-10-17  本文已影响0人  一岁一枯荣啊

一,什么是CAS?

(Conmpare And Swap)对比并替换。它将内存的内容与对比值进行校验,相同则替换,否则返回false.

两步操作,但是由于底层硬件的支持,两步操作能一步完成,避免独占锁资源浪费,保证了原子性

/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre/lib/rt.jar!/java/util/concurrent/atomic

二、JAVA中CAS是怎么是实现的

JAVA中的CAS操作都是通过sun包下Unsafe类实现的,而Unsafe类中的方法都是native方法,由JVM本地实现

 */
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

    /**
     * Atomically sets to the given value and returns the old value.
     *
     * @param newValue the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * <p><a href="package-summary.html#weakCompareAndSet">May fail
     * spuriously and does not provide ordering guarantees</a>, so is
     * only rarely an appropriate alternative to {@code compareAndSet}.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

    /**
     * Atomically decrements by one the current value.
     *
     * @return the previous value
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the previous value
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

    /**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

    /**
     * Atomically decrements by one the current value.
     *
     * @return the updated value
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }


三、ABA问题

比如内存中一数据 str="A";

第一步: 线程1取出str 的值"A",准备执行变更为"D",还未执行
第二步: 线程2取出str 的值"A" ,执行cas("A","B") ,把值变成了"B"
第三步: 线程3取出str 的值"B" ,执行cas("B","A") ,把值变成了"A"
第四步: 线程1继续执行cas("A","D")

这个过程就是有ABA问题存在的。因为在线程一执行的中间,数据已经被其他线程修改从而发生了变化,虽然恢复了原值,但是线程1没有感知到,以为没有发生过变化,这是不能被忽略的。

解决方式:JAV提供了时间戳的CAS。AtomicStampedReference

三、哪里用到了CAS

上一篇下一篇

猜你喜欢

热点阅读