Java源码Atomic部分源码解析

Posted 低调的洋仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java源码Atomic部分源码解析相关的知识,希望对你有一定的参考价值。

 

AtomicXXX

加了volatile保证了可见性。

本质上这一系列的都是采用的CAS的方式来更新原来的值的。

boolean实际上是用的int值来存储的。

 

AtomicXXXArray

 

    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final int base = unsafe.arrayBaseOffset(long[].class);
    private static final int shift;
    private final long[] array;

基本的操作大体的意思应该是:

 

计算出来的地址就是:基础地址+偏移量=最终要定位的元素的地址。

然后Cas操作修改这个地址上的数据。

AtomicReferenceArray里面多了一个arrayFieldOffset,这个域用来支持反序列化的。其次,与AtomicIntegerArray不同,AtomicReferenceArray并没有scale域,取而代之的是shift域。阅读代码可知,其实目的都是计算rawIndex = base + index * scale,只不过AtomicReferenceArray里面把一部分运算转换为等价的位操作(当然前提是scala为2的幂)。(了解更多位操作技巧,可参考Hacker's Delight)。

 

    public final void set(int i, long newValue) 
        unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
    

 

 

AtomicXXXFieldUpdater

 

 

 

 

  • 原子域更新器,一般用于一些原子同步结构中。
    /**
     * Standard hotspot implementation using intrinsics
     */
    private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> 
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private final long offset;
        private final Class<T> tclass;
        private final Class cclass;

 

AtomicIntegerFieldUpdaterImpl构造过程中会目标class,和目标域的访问权限、还要要检查目标域是否为int型,是否由volatile修饰、当然还要获取目标域的偏移量,为后面的CAS操作做准备。

AtomicLongFieldUpdater,结构和AtomicIntegerFieldUpdater类似,有一点区别就是,它有两个实现,根据平台是否支持8字节的CAS操作,来选择不同的实现

AtomicReferenceFieldUpdater和AtomicIntegerFieldUpdater类似的结构,AtomicReferenceFieldUpdater一般用于某些原子数据结构中,支持某些节点的引用域的独立原子更新操作。

其实直接使用AtomicReference也可以完成类似的工作,那么为什么要使用AtomicReferenceFieldUpdater?主要原因还是为了提高性能。假设要设计一个支持原子操作的队列,队列的链接节点必然会进行频繁的操作,如果利用AtomicReference表示这些结点,那么AtomicReference本身的创建过程也需要一些开销,使用AtomicReferenceFieldUpdater可以省去这些开销。辅助创建一个实例,

 

AtomicStampedReference & AtomicMarkableReference

防止ABA问题,分别靠时间戳和Mark标记位来方式ABA问题的发生。

 

private static class Pair<T> 
        final T reference;
        final int stamp;
        private Pair(T reference, int stamp) 
            this.reference = reference;
            this.stamp = stamp;
        
        static <T> Pair<T> of(T reference, int stamp) 
            return new Pair<T>(reference, stamp);
        
    
 private static class Pair<T> 
        final T reference;
        final boolean mark;
        private Pair(T reference, boolean mark) 
            this.reference = reference;
            this.mark = mark;
        
        static <T> Pair<T> of(T reference, boolean mark) 
            return new Pair<T>(reference, mark);
        
    

 

 

 

 

 

 

 

 

 

以上是关于Java源码Atomic部分源码解析的主要内容,如果未能解决你的问题,请参考以下文章

Java高并发之无锁与Atomic源码分析

linux源码解析12–page数据结构

Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例

Java 集合系列06之 Vector详细介绍(源码解析)和使用示例

Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例

Java 集合系列13之 WeakHashMap详细介绍(源码解析)和使用示例