近期评论

深入CAS原理

JDK中所有的CAS到最后都要用到这个方法:

public final native boolean compareAndSwapObject
(Object var1, long var2, Object var4, Object var5);
这个方法有4个参数,奇怪的是序号不是1234,而是1245,没有javadoc和任何注释,是个native方法,代码实现是用C++写的。

这个方法到底干什么的?

下面来分析这个几个参数:

Object var1是要修改的目标对象。
long var2是要修改的对象的属性,为什么是整数,因为传入C++时,
通过var1这个结构体指针和偏离值得到字段的。
这个偏离值怎么获得,通过下面这个方法,next是字段名:
UNSAFE.objectFieldOffset(k.getDeclaredField("next"));
Node对象有个属性next,cas方法compareAndSwapObject要修改的就是Node对象的next属性值,
通过得到这个next的参数的偏离值比如12,来修改它。
Object var4是要对比的值,拿var4和Node对象的next属性对比,如果相同就用var5替换
Object var5要拿来替换的对象。

完整的代码如下:

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.Objects;

/**
 * Created by TangHaiyang on 2019/8/19.
 * 验证cas的关键方法objectFieldOffset
 */
public class TestUnsafe {

    public static void main(String[] args) {
        Node node = new Node();
        node.seq=10;

        Node node2 = new Node();
        node2.seq=20;

        Node node3 = new Node();
        node3.seq=20;

        System.out.println(node2.equals(new Node()));
        System.out.println(node2.equals(node3));

        /**
         * 原子操作, 通过CAS方法更新node的next属性
         * 是否等于null,等于则用new node()替换并返回true,否则不做任何操作并返回false
         * 在jdk源码的下面几个集合中广泛用到了compareAndSwapObject,
         * 通常是跟null对比然后替换为指定的对象
         * ConcurrentHashMap
         * ConcurrentLinkedQueue
         * ConcurrentSkipListMap
         * ConcurrentLinkedDeque
         * SynchronousQueue
         */
        boolean flag1 = node.casNext(null,new Node());
        boolean flag2 = node.casNext(null,new Node());
        boolean flag3 = node.casNext(node2,new Node());
        System.out.println(flag1);
        System.out.println(flag2);
        System.out.println(flag3);
    }

    private static class Node{
        volatile Node next;
        volatile int seq;
        private static final sun.misc.Unsafe UNSAFE;
        private static final long nextOffset;
        static {
            try {
                /*
                 * sun.misc.Unsafe.getUnsafe()会得到一个SecurityException,
                 * 这个类只有被JDK信任的类才能通过这个方法实例化
                 * 但是可以通过反射拿到对应的实例
                 * UNSAFE = sun.misc.Unsafe.getUnsafe();
                */
                UNSAFE = getUnsafe();
                Class<?> k = Node.class;
                if(Objects.isNull(UNSAFE)) {
                    nextOffset = 0;
                }else {
                    nextOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("next"));
                }
            } catch (Exception e) {
                throw new Error(e);
            }
        }

        /**
         * 使用Unsafe CAS方法
         * @param cmp 目标值与cmp比较equal方法,
         * 如果相等就更新返回true;如果不相等就不更新返回false;
         * @param val 需要更新的值;
         * @return boolean
         */
        boolean casNext(Node cmp, Node val) {
            /*
             * compareAndSwapObject(Object var1, long var2, Object var3, Object var4)
             * var1 操作的对象
             * var2 操作的对象属性是个偏离值,对C++的结构体来说,var1是指针,
             * 指针加偏离值就能得到结构体成员,相当远java对象属性
             * var3 var2对应的属性与var3比较,相等才更新
             * var4 更新值
             */
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
        }

        /**
         * 获取Unsafe的方法
         * 获取了以后就可以愉快的使用CAS啦
         * @return Unsafe
         */
        private static Unsafe getUnsafe() {
            try {
                Field f = Unsafe.class.getDeclaredField("theUnsafe");
                f.setAccessible(true);
                return (Unsafe)f.get(null);
            } catch (Exception e) {
                return null;
            }
        }
    }
}

7 Responses to “深入CAS原理”

  • oprol evorter说道:

    Very efficiently written article. It will be valuable to everyone who employess it, as well as me. Keep up the good work – can’r wait to read more posts.

  • TittysSeerwoT说道:

    XRumer 19.0 + XEvil 4.0: innovative software complex for breaking any Captcha

    1. Powerful Neuronets: XEvil OCR can solve more than 12000 of different types of Captcha’s,
    including such of popular, like Google CAPTCHA’s ReCaptcha v2, v3 (in XEvil 4.0 Ultra only!), Captcha.Com, SolveMedia, Bing-Captcha,
    Facebook-captcha and Bitfinex-captcha, Yandex-captcha, DLE-captcha, VBulletin-Captcha, and a lot of other types!

    2. Very High speed and precision: recognition speed 0.01 .. 0.02 second per image (but only 1 second in DEMO version!),
    XEvil can bypass and solve wide types spectre of captcha with high precision,
    without depending of difficulty, distortion, noises, fonts, colors.

    3. Very simple UI: just 3 main buttons to start recognition,
    so XEvil easily to use with a wide spectre programs of SEO, SMM, Analytics,
    Mass Auto-Registering/Posting/Sending/Bruteforcing/CryptoCurrency Mining programs.

    Interested? 😉
    Just do search in google “XEvil for Free”.

  • cited here说道:

    I was talking to my mom on Sunday when I discovered this. I just now discovered this article but I’m at my school as I write this so I’ll have to read the rest of this later on when I can find the time and I’m able to read it without distractions. I saw your website on my Google feed. I love all of the points you have made here. Certainly a ton of details to consider.

  • discount drug说道:

    This has been such a really awesome time! You have really changed my way of thinking on more than a few things that I’ve thought were true for most of my adult life. It’s really simple, yet really effective for some people. I’ve always been curious about the subject and I am planning to do more research on the subject some day soon. I’m sure your points will help all who discover it. I just don’t have no idea where to go from here.

  • 不赖!真的不赖!

  • 混球网说道:

    天气越来越冷了,躲在家里刷刷博客也挺好!

  • Fortnite V Bucks说道:

    Thanks a lot

Leave a Reply