• AtomicInteger相关类


    引用地址:http://blog.csdn.net/xh16319/article/details/17056767

    在java6以后我们不但接触到了Lock相关的锁,也接触到了很多更加乐观的原子修改操作,也就是在修改时我们只需要保证它的那个瞬间是安全的即可,经过相应的包装后可以再处理对象的并发修改,以及并发中的ABA问题,本文讲述Atomic系列的类的实现以及使用方法,其中包含:

    基本类:AtomicInteger、AtomicLong、AtomicBoolean;

    引用类型:AtomicReference、AtomicReference的ABA实例、AtomicStampedRerence、AtomicMarkableReference;

    数组类型:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

    属性原子修改器(Updater):AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater

     

    在使用Atomic系列前,我们需要先知道一个东西就是Unsafe类,全名为:sun.misc.Unsafe,这个类包含了大量的对C代码的操作,包括很多直接内存分配以及原子操作的调用,而它之所以标记为非安全的,是告诉你这个里面大量的方法调用都会存在安全隐患,需要小心使用,否则会导致严重的后果,例如在通过unsafe分配内存的时候,如果自己指定某些区域可能会导致一些类似C++一样的指针越界到其他进程的问题,不过它的具体使用并不是本文的重点,本文重点是Atomic系列的内容大多会基于unsafe类中的以下几个本地方法来操作:

    对象的引用进行对比后交换,交换成功返回true,交换失败返回false,这个交换过程完全是原子的,在CPU上计算完结果后,都会对比内存的结果是否还是原先的值,若不是,则认为不能替换,因为变量是volatile类型所以最终写入的数据会被其他线程看到,所以一个线程修改成功后,其他线程就发现自己修改失败了。

    参数1:对象所在的类本身的对象(一般这里是对一个对象的属性做修改,才会出现并发,所以该对象所存在的类也是有一个对象的)

    参数2:这个属性在这个对象里面的相对便宜量位置,其实对比时是对比内存单元,所以需要属性的起始位置,而引用就是修改引用地址(根据OS、VM位数和参数配置决定宽度一般是4-8个字节),int就是修改相关的4个字节,而long就是修改相关的8个字节。

    获取偏移量也是通过unsafe的一个方法:objectFieldOffset(Fieldfield)来获取属性在对象中的偏移量;静态变量需要通过:staticFieldOffset(Field field)获取,调用的总方法是:fieldOffset(Fieldfield)

    参数3:修改的引用的原始值,用于对比原来的引用和要修改的目标是否一致。

    参数4:修改的目标值,要将数据修改成什么。

    [java] view plaincopy
     
    1. public final native boolean compareAndSwapObject(Object paramObject1, long paramLong, Object paramObject2, Object paramObject3);  
    2.   
    3. public final native boolean compareAndSwapInt(Object paramObject, long paramLong, int paramInt1, int paramInt2);  

     

    #对long的操作,要看VM是否支持对Long的CAS,因为有可能VM本身不支持,若不支持,此时运算会变成Lock方式,不过现在VM都基本是支持的而已。

    [java] view plaincopy
     
    1. public final native boolean compareAndSwapLong(Object paramObject, long paramLong1, long paramLong2, long paramLong3);  

     

    我们不推荐直接使用unsafe来操作原子变量,而是通过java封装好的一些类来操作原子变量。

    本文最后要介绍的部分为Updater也就是修改器,它算是Atomic的系列的一个扩展,Atomic系列是为你定义好的一些对象,你可以使用,但是如果是别人已经在使用的对象会原先的代码需要修改为Atomic系列,此时若全部修改类型到对应的对象相信很麻烦,因为牵涉的代码会很多,此时java提供一个外部的Updater可以对对象的属性本身的修改提供类似Atomic的操作,也就是它对这些普通的属性的操作是并发下安全的,分别由:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceUpdater,这样操作后,系统会更加灵活,也就是可能那些类的属性只是在某些情况下需要控制并发,很多时候不需要,但是他们的使用通常有以下几个限制:

    限制1:操作的目标不能是static类型,前面说到unsafe的已经可以猜测到它提取的是非static类型的属性偏移量,如果是static类型在获取时如果没有使用对应的方法是会报错的,而这个Updater并没有使用对应的方法。

    限制2:操作的目标不能是final类型的,因为final根本没法修改。

    限制3:必须是volatile类型的数据,也就是数据本身是读一致的。

    限制4:属性必须对当前的Updater所在的区域是可见的,也就是private如果不是当前类肯定是不可见的,protected如果不存在父子关系也是不可见的,default如果不是在同一个package下也是不可见的。

    实现方式:通过反射找到属性,对属性进行操作,但是并不是设置accessable,所以必须是可见的属性才能操作。

  • 相关阅读:
    Java分布式锁
    深度神经网络学习过程中的梯度消失问题
    深度神经网络学习过程中的梯度消失问题
    .net下 本地锁、redis分布式锁、zk分布式锁的实现
    .net下 本地锁、redis分布式锁、zk分布式锁的实现
    CLR共享程序集和强命名程序集
    CLR共享程序集和强命名程序集
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 接线过程
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 接线过程
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 安装过程
  • 原文地址:https://www.cnblogs.com/lanhzbupt/p/4131813.html
Copyright © 2020-2023  润新知