• JDK AtomicInteger 源码分析


    @(JDK)[AtomicInteger]

    JDK AtomicInteger 源码分析

    Unsafe

    实例化

    Unsafe在创建实例的时候,不能仅仅通过new Unsafe()或者Unsafe.getUnsafe()来获取,因为Java会进行安全校验,只有信任的代码,才能够获取实例。

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if(var0.getClassLoader() != null) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }
    

    要达到上述对应的ClassLoader为空,只有通过BootStrapLoader来加载才可以。(可以通过bootclasspath实现)
    java -Xbootclasspath:/usr/jdk1.7.0/jre/lib/rt.jar:. com.mishadoff.magic.UnsafeClient

      Unsafe里面有一个静态变量,theUnsafe,另一种方式就是通过反射来获取该实例。
    private static final Unsafe theUnsafe;

    Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
    theUnsafe.setAccessible(true);
    Unsafe unsafe = (Unsafe) theUnsafe.get(null);
    

    避免初始化

    可以使用allocateInstance方法来绕过构造方法的调用。

    public class UnsafeDemo {
    
        private UnsafeDemo() {
            throw new IllegalStateException("非法访问");
        }
    
        public static void main(String[] args)
            throws Exception {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            Unsafe unsafe = (Unsafe) theUnsafe.get(null);
            System.out.println(unsafe.allocateInstance(UnsafeDemo.class));
        }
    }
    

    并发

      可以通过Unsafe. compareAndSwap方法来实现Lock-free数据结构。使用的时候一般都会采用while循环在等待(Spin Lock),以及volatile来对内存数据变更能及时反应出来,在JDK里面AtomicInteger等应用到了。

    字段的偏移

    可以通过unsafe.objectFieldOffset来获取类的字段偏移,一般可以和Unsafe. compareAndSwap结合来使用。
    如:

    valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"))
    unsafe.compareAndSwapInt(this, valueOffset, expect, update)
    

    AtomicInteger

    字段变量

    在AtomicInteger里面,主要通过使用CAS和volatile来实现。

    public class AtomicInteger extends Number implements java.io.Serializable {
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        // value字段的偏移,用于compareAndSwapInt方法
        private static final long valueOffset;
    
        // 这里volatile用于在并发的时候变更值,能够及时的反应到其它线程
    	private volatile int value;
    }
    

    具体方法

    getAndSet

    public final int getAndSet(int newValue) {
    	/* 这里就用到了循环来控制,直到成功,类似自旋锁的方式,在冲突不大的情况下,性能会得到比较好的提升,但是同时也会比较耗CPU,因为是在一直在尝试。同时,在冲突比较大的时候,建议还是使用Lock */
        for (;;) {
            int current = get();
            if (compareAndSet(current, newValue))
                return current;
        }
    }
    

    compareAndSet/weakCompareAndSet

    这两个方法,和上面的区别在于只会调用一次,那么就需要开发者考虑失败的情况。

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    

    参考资料

    Unsafe:

    1. http://www.docjar.com/html/api/sun/misc/Unsafe.java.html
    2. http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
    3. http://www.javaworld.com/article/2952869/java-platform/understanding-sun-misc-unsafe.html

    CAS

    1. https://en.wikipedia.org/wiki/Test-and-set
    2. https://en.wikipedia.org/wiki/Volatile_(computer_programming)
    3. https://en.wikipedia.org/wiki/ABA_problem
    4. http://ifeve.com/better_atomicinteger/
  • 相关阅读:
    JS从后台获取数据,前台动态添加tr标签中的td标签
    Java方式导出EXCEL表格
    框架搭建相关博文
    Spring框架相关博文集
    Eclipse相关工具使用
    关于Spring Boot的博客集合
    Springboot spring data jpa 多数据源的配置01
    springboot1.X 到2.X 的改变
    Spring-Boot devtools项目自动重启
    JSR 303
  • 原文地址:https://www.cnblogs.com/jabnih/p/6517214.html
Copyright © 2020-2023  润新知