(6)Atomic类原子操作

    对于简单的计数和加减操作,lock和synchronized的锁粒度太大,容易导致高并发时效率问题。J.U.C包中提供了一个更加高效的解决方案——Atomic类。它的底层通过CAS操作来实现并发安全性。

    Atomic类里提供了4种操作对象,下面分别介绍。

一、 基本原子类型

  AtomicBoolean

  AtomicInteger

  AtomicLong

  以AtomicInteger为例,他们常用的方法

getAndIncrement

先返回原值,再+1
incrementAndGet 先+1,再返回+1后的值

getAndDecrement

先返回原值,再-1
decrementAndGet 先-1,再返回-1后的值
addAndget(int value) 先+value,然后返回计算的值

getAndAdd(int value)

先返回原值,然后将原值+value
compareAndSet(e, n)

原值若是期望值e就设置为新值new,返回true;

否则,就不更改,返回false 

accumulateAndGet(x, IntBinaryOperator  function)

使用当前值与 x 进行function计算,并将计算结果返回
getAndaccumulate(x, IntBinaryOperator function) 先返回当前值,然后将当前值与x进行function计算,结果存为新值

前面的都比较好理解,这里就举最后两个的例子:

AtomicInteger a = new AtomicInteger(2);
System.out.println(a.getAndAccumulate(5, Math::max));   //2   ,先返回后计算max(a, 5)
System.out.println(a);   //5  ,max(a,5)之后的值存入了a

System.out.println(a.accumulateAndGet(10, Math::max));  //10
System.out.println(a);   //10

二、原子数组

  原子数组就是可以声明原子变量的数组,然后对这个数组的各个变量进行原子操作。

int[] data = {1,2,3,4};
AtomicIntegerArray array = new AtomicIntegerArray(data);
System.out.println(array.getAndSet(1, 10));     //对[1]的数设置为10
System.out.println(array.get(1));               //10

   它的方法与基本原子类型基本相同,只是操作的时候第一个操作数是数组的下标。

三、原子抽象类型

  我们可以对一个类的对象进行原子操作,方法就是用到AtomicReference<>

public class User {
    public volatile int age;

    public User(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

public static void main(){
    AtomicReference<User> user = new AtomicReference<>();  //声明User为原子抽象类型
    System.out.println(user);         //null
    User user1 = new User(10);
    System.out.println(user1);       //User@74a14482
    user.getAndSet(user1);                                 //对user对象进行原子操作
    System.out.println(user);        //User@74a14482,与user1相同
}

    需要说明的是, User类为原子抽象类型,指我们可以对User类的对象进行原子操作,而不是我们可以对User类中的一个属性变量可以原子操作(如 int age, 是不能原子操作的)。能对其进行操作的是下一个——原子字段。

 

四、原子(抽象类型)字段

  原子字段是指对一个类中的某一个字段进行原子操作。

public static void main(){
    User user = new User(15);
    //将User.class 中的 "age"字段声明为原子字段
    AtomicIntegerFieldUpdater<User> data = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
    data.set(user, 25);   //设置时需要指明对象

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println(data.getAndIncrement(user));  //25
            System.out.println(data.get(user));              //26
        }
    }).start();

}

  因为进行原子操作的是类实例中的一个字段,所以操作的时候需要指明操作实例。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章