Java 并发-使用原子类
本文介绍 Java 并发编程中的原子类,如原子类的基本原理介绍,原子基本数据类型、原子引用类型、原子的属性更新器、原子数组以及累加器的使用

# Java 并发-使用原子类

# 原子类简介

  1. 原子类是 Java atomic 包中提供的一系列原子操作的类,大多以 Atomic 开头

  2. 原子类一种无锁方案,原理是使用 CAS 指令,因为不需要涉及到操作系统内核层面的加锁,性能很好

  3. CAS 指令封装在 Unsafe 类的本地方法中,底层是硬件支持的 compare_exchange 指令

  4. CAS 指令是先比较判断值是否更新,没更新就交换数据,有更新就循环尝试

    示例代码模拟 CAS 和自旋操作

    class Adder {
        private volatile int count;
        public void addOne() {
            // 存储一份当前值和 +1 后的值
            int oldVal, newVal;
            do {
                oldVal = this.count;
                newVal = oldVal + 1;
            } while (!cas(oldVal, newVal));
        }
    
        /**
          * 利用 synchronized 模拟原子的 CAS 操作
          *
          * @param oldVal 旧值
          * @param newVal 新值
          * @return 比较旧值,没有更新才设置新值,返回 true
          */
        private synchronized boolean cas(int oldVal, int newVal) {
            // 比较数据是否发生改变
            if (oldVal == this.count) {
                this.count = newVal;
                return true;
            }
            return false;
        }
    }
    

# 原子类型

# 基本数据类型

  1. 原子类

    有 AtomicBoolean、AtomicInteger 和 AtomicLong

  2. 常用 API

    AtomicInteger integer = new AtomicInteger();
    // i++
    integer.getAndIncrement();
    // --i
    integer.decrementAndGet();
    // 加上指定值,返回加前的值
    integer.getAndAdd(delta);
    
  3. 使用场景:

    原子的更新一个基本数据类型

# 对象引用类型

  1. 原子类

    有 AtomicReference、AtomicStampedReference 和 AtomicMarkableReference

  2. 常用 API

    AtomicReference<User> atomicUser = new AtomicReference<>();
    atomicUser.set(new User("张三", 20));
    atomicUser.getAndAccumulate(new User("李四", 21), (user, user2) -> user);
    
  3. 使用场景:

    原子的更新整个对象

    AtomicStampedReference 和 AtomicMarkableReference 在更新时会添加版本号,可以解决 ABA 问题

# 对象属性更新器

  1. 原子类

    有 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater

  2. 常用 API

    User user = new User("张三", 20);
    // 年龄更新器,age 属性需要声明为 volatile
    AtomicIntegerFieldUpdater<User> fieldUpdater = 
        AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
    // 年龄加一
    fieldUpdater.getAndAdd(user, 1);
    
  3. 使用场景:

    原子的更新对象的某个属性

# 数组

  1. 原子类

    有 AtomicIntegerArray、AtomicLongArray 和 AtomicReferenceArray

  2. 常用 API

    AtomicIntegerArray array = new AtomicIntegerArray(1);
    // 下标 i 的元素,加上 delta
    array.addAndGet(i, delta)
    
  3. 使用场景:

    原子的更新数组元素,和原子基本数据类型使用方式类似,方法参数需要转入索引

    比原子基本数据类型的数组更节约空间

# 累加器

  1. 原子类

    有 DoubleAccumulator、DoubleAdder、LongAccumulator 和 LongAdder

  2. 常用 API

    LongAdder adder = new LongAdder();
    // +1
    adder.increment();
    // 获取 int 值
    adder.intValue();
    
  3. 使用场景:

    与原子基本数据类型相比,专门用来执行累加操作,性能更好

Comment here, be cool~

Copyright © 2020 CadeCode

Theme 2zh powered by VuePress

本页访问次数 0

Loading