原子操作类

概述

  在Atomic包里一共有13个类,四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新字段。Atomic包里的类基本都是使用Unsafe实现的包装类。
  万变不离其宗,JDK提供的原子更新类和方法虽多,但最终依赖的都是CAS操作。

原子更新基本类型类

  用于通过原子的方式更新基本类型,Atomic包提供了以下三个类:

   1. AtomicBoolean:原子更新布尔类型
   2. AtomicInteger:原子更新整型
   3. AtomicLong:原子更新长整型

  这三个类中的数据都是以volatile声明,所以get()和set()方法就可以达到volatile的内存语义。
  compareAndSet()weakCompareAndSet()是有条件的修改程序的方法,这两个方法都要取用两个参数:在方法启动时预期数据所具有的的值,以及要把数据所设定成的值。它们都只会在变量具有预期值的时候才会设定成新值,如果当前值不等于预期值,该变量就不会被重新赋值并且返回false。这两个方法之间有什么区别吗?第二个方法少了一项保证:如果方法返回的值false,该变量不会被变动,但是这并不表示现有值不是预期值,也就是说,这个方法不管初始值是否是预期值都可能会无法更新改值。
  incrementAndGet(),decrementAndGet(),getAndIncrement()和getAndDecrement()提供了前置递增,前置递减,后递增和后递减,之所以有这些方法,是因为这些操作都不是atomic的。
  addAndGet()和getAndAdd()提供了”前置”和”后置”的运算符给指定值的加法运算,它们能够让程序对变量增或者减一个指定值,包括了负值,所以我们就不需要一个相对的减法运算。
  为一个AtomicLong对象设置一个值,jvm会确保其他线程读取到最新值,原子类和voliatile变量也是一样的,这是由依赖于硬件的系统指令(如x86的xchg)实现的。lazySet()却是无法保证这一点的方法,所以其他线程在之后的一小段时间里还是可以读到旧的值。
  AtomicBoolean是先把Boolean转换成整型,再使用compareAndSwapInt进行CAS,所以原子更新char、float、double也可以用类似的思路来实现。

原子更新数组类

  通过原子的方式更新数组里的某个元素,Atomic包提供了以下3个类:

   1. AtomicIntegerArray:原子更新整型数组里的元素。
   2. AtomicLongArray:原子更新长整型数组里的元素。
   3. AtomicReferenceArray:原子更新引用类型数组里的元素。

原子更新引用类型

  原子更新基本类型的AtomicInteger,只能更新一个变量,如果要原子的更新多个变量,就需要使用这个原子更新引用类型提供的类。Atomic包提供了以下三个类:

  1. AtomicReference:原子更新引用类型。
  2. AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
  3. AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子的更新一个布尔类型的标记位和引用类型。构造方法是AtomicMarkableReference(V initialRef, boolean initialMark)
public class AtomicReferenceTest {

    public static AtomicReference<user> atomicUserRef = new AtomicReference</user><user>();

    public static void main(String[] args) {
        User user = new User("conan", 15);
        atomicUserRef.set(user);
        User updateUser = new User("Shinichi", 17);
        atomicUserRef.compareAndSet(user, updateUser);
        System.out.println(atomicUserRef.get().getName());
        System.out.println(atomicUserRef.get().getOld());
    }

    static class User {
        private String name;
        private int old;

        public User(String name, int old) {
            this.name = name;
            this.old = old;
        }

        public String getName() {
            return name;
        }

        public int getOld() {
            return old;
        }
    }
}

原子更新字段类

  如果我们只需要某个类里的某个字段,那么就需要使用原子更新字段类,Atomic包提供了以下三个类:

   1. AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
   2. AtomicLongFieldUpdater:原子更新长整型字段的更新器。
   3. AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于原子的更数据和数据的版本号,可以解决使用CAS进行原子更新时,可能出现的ABA问题。

参考链接:http://ifeve.com/java-atomic/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值