JDK源码——Atomic包(一)

包介绍

JDK的atomic包提供了一组原子类,用于多线程环境中的原子操作,确保线程安全和高性能

Atomic包是Java在并发编程中的重要工具,它利用CAS(Compare-And-Swap)机制保证操作的原子性,同时避免了重量级锁的使用,提高了并发性能。Atomic包中的类通过底层处理器提供的原子指令实现,但不同的CPU架构可能提供的原子指令不同,有时可能需要某种形式的内部锁,因此不能绝对保证线程不被阻塞。
在这里插入图片描述

基本类型

AtomicInteger

提供了一种线程安全的方式来操作整数。
在这里插入图片描述
主要提供了以下方法:
在这里插入图片描述

  1. getAndIncrement(): 获取当前值并自增,返回旧值。
  2. get(): 获取当前值。
  3. compareAndSet(int expect, int update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。
  4. getAndSet(int newValue): 获取当前值并设置为指定的新值,返回旧值。
  5. floatValue(): 将当前值转换为 float 类型。
  6. getAndAdd(int delta): 获取当前值并加上指定的增量(delta),返回旧值。
  7. getAndUpdate(IntUnaryOperator updateFunction): 获取当前值并应用给定的一元操作函数(updateFunction),返回旧值。
  8. intValue(): 将当前值转换为 int 类型。
  9. getAndAccumulate(int x, IntBinaryOperator accumulatorFunction): 获取当前值并与给定的值(x)应用二元操作函数(accumulatorFunction),返回旧值。
  10. toString(): 返回当前值的字符串表示形式。
  11. lazySet(int newValue): 设置当前值为指定的新值,但不保证立即可见性,可能会延迟到下一次访问。
  12. incrementAndGet(): 自增并返回新值。
  13. accumulateAndGet(int x, IntBinaryOperator accumulatorFunction): 与给定的值(x)应用二元操作函数(accumulatorFunction)并返回结果。
  14. decrementAndGet(): 自减并返回新值。
  15. longValue(): 将当前值转换为 long 类型。
  16. addAndGet(int delta): 增加指定的增量(delta)并返回新值。
  17. doubleValue(): 将当前值转换为 double 类型。
  18. weakCompareAndSet(int expect, int update): 类似于 compareAndSet,但如果当前值不等于预期值,它可能不会立即失败,而是尝试再次进行比较和设置。这在某些情况下可以提高性能,但可能导致不一致的结果。
  19. updateAndGet(IntUnaryOperator updateFunction): 应用给定的一元操作函数(updateFunction)并返回结果。
  20. set(int newValue): 设置当前值为指定的新值。

原理

  1. 原子性操作:AtomicInteger使用CAS(比较替换)算法来实现其内部的值的原子性更新。CAS算法是硬件级别的原子操作,它可以在没有锁的情况下进行线程安全的更新。

  2. Unsafe类:AtomicInteger的内部实现使用了Unsafe类的native方法,如compareAndSwapInt,这是一个底层的、高效的原子操作方法,它直接与操作系统和硬件交互,实现了原子性的保证。

/**
通过调用Unsafe.getUnsafe()方法获取Unsafe实例。Unsafe类提供了一些底层操作,可以直接访问对象和内存,绕过了Java的安全检查机制。

定义了一个静态常量valueOffset,用于存储字段"value"在内存中的偏移量。

在静态初始化块中,使用unsafe.objectFieldOffset方法获取字段"value"的偏移量。这个方法需要一个Field对象作为参数,因此需要先通过反射获取AtomicInteger类的"value"字段。

如果获取偏移量的过程中发生异常(例如找不到字段),则抛出一个Error。

**/
  private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
  1. 字段更新:AtomicInteger使用volatile关键字声明其内部值字段,确保字段的可见性和有序性,防止指令重排序导致的问题。
 private volatile int value;
  1. 方法实现:AtomicInteger提供了一系列的方法,如getAndIncrementcompareAndSet等,这些方法都是利用CAS算法来实现的,它们可以在没有锁的情况下,保证操作的原子性。
public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

 public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
  1. 性能优势:由于AtomicInteger不需要使用锁,它通常比使用synchronized关键字或者显式锁(如ReentrantLock)的性能要好,尤其是在高并发的情况下。

  2. 内存开销:AtomicInteger相对于普通的Integer会有稍微大一点的内存开销,因为它需要额外的内存来存储一些操作所需的元数据。

  3. 限制:尽管AtomicInteger提供了原子性的保证,但是它不能保证操作的“逻辑原子性”。例如,如果你需要检查值,然后基于这个值进行更新(比如计数器小于10就增加),这样的操作序列就不能保证原子性,因为这个过程涉及到多个步骤,而CAS只能保证单个操作的原子性。

  4. 可扩展性:AtomicInteger是可扩展的,意味着你可以用它作为更复杂原子操作的基础,通过组合和扩展AtomicInteger的功能,可以构建更复杂的原子操作。

  5. 线程兼容性:AtomicInteger的操作是线程兼容的,这意味着在多线程环境中,你可以安全地使用AtomicInteger而不用担心线程安全问题。

  6. 使用场景:AtomicInteger适用于那些需要线程安全的整数操作,但不需要使用锁或者不希望有锁带来的性能开销的场景。

AtomicBoolean

类提供了一种线程安全的方式来操作布尔值。
在这里插入图片描述

主要提供了以下方法:
在这里插入图片描述

  1. getAndSet(boolean newValue): 将当前值设置为指定的新值,并返回旧值。这是一个原子操作,确保在多线程环境下的一致性。

  2. set(boolean newValue): 将当前值设置为指定的新值。这也是一个原子操作。

  3. get(): 获取当前的布尔值。这个方法是非原子的,但在多线程环境中使用时,由于其他原子操作的存在,可以保证读取到的值是一致的。

  4. compareAndSet(boolean expect, boolean update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。这是一个典型的CAS(Compare-and-Swap)操作,通常用于无锁编程。

  5. lazySet(boolean newValue): 将当前值设置为指定的新值,但可能会延迟该操作直到下一次访问。这是一种优化手段,可以减少不必要的内存屏障开销。

  6. weakCompareAndSet(boolean expect, boolean update): 类似于 compareAndSet,但如果当前值不等于预期值,它可能不会立即失败,而是尝试再次进行比较和设置。这在某些情况下可以提高性能,但可能导致不一致的结果。

  7. toString(): 返回当前布尔值的字符串表示形式。这个方法是非原子的,但在多线程环境中使用时,由于其他原子操作的存在,可以保证读取到的值是一致的。

AtomicLong

类提供了一种线程安全的方式来操作长整数。
在这里插入图片描述

主要提供了以下方法:
在这里插入图片描述

  1. VMSupportsCS8(): 返回一个布尔值,表示虚拟机是否支持CS8(Compare and Swap)操作。
  2. longValue(): 获取当前值作为长整型(long)。
  3. intValue(): 获取当前值作为整型(int)。
  4. toString(): 返回当前值的字符串表示形式。
  5. incrementAndGet(): 自增并返回新值。
  6. getAndAccumulate(long x, LongBinaryOperator accumulatorFunction): 获取当前值并与给定的值(x)应用二元操作函数(accumulatorFunction),返回旧值。
  7. getAndSet(long newValue): 获取当前值并设置为指定的新值,返回旧值。
  8. doubleValue(): 将当前值转换为双精度浮点数(double)。
  9. set(long newValue): 设置当前值为指定的新值。
  10. weakCompareAndSet(long expect, long update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。
  11. getAndUpdate(LongUnaryOperator updateFunction): 获取当前值并应用给定的一元操作函数(updateFunction),返回旧值。
  12. getAndIncrement(): 获取当前值并自增,返回旧值。
  13. accumulateAndGet(long x, LongBinaryOperator accumulatorFunction): 与给定的值(x)应用二元操作函数(accumulatorFunction)并返回结果。
  14. getAndAdd(long delta): 获取当前值并加上指定的增量(delta),返回旧值。
  15. get(): 获取当前值。
  16. lazySet(long newValue): 设置当前值为指定的新值,但不保证立即可见性,可能会延迟到下一次访问。
  17. compareAndSet(long expect, long update): 如果当前值等于预期值(expect),则将其更新为新的值(update)。如果更新成功,返回 true;否则返回 false。
  18. updateAndGet(LongUnaryOperator updateFunction): 应用给定的一元操作函数(updateFunction)并返回结果。
  19. floatValue(): 将当前值转换为单精度浮点数(float)。
  20. addAndGet(long delta): 增加指定的增量(delta)并返回新值。
  21. getAndDecrement(): 获取当前值并自减,返回旧值。
  22. decrementAndGet(): 自减并返回新值。

数组操作

AtomicIntegerArray

与AtomicLongArray类似,但是它用于操作int类型的数组。它也提供了一系列的原子操作方法,如get、set、compareAndSet等,以确保在多线程环境下对数组元素的操作是原子性的。
在这里插入图片描述
提供的以下方法:
在这里插入图片描述

  1. getAndIncrement(int): 获取指定索引位置的当前值,并将其自增1。返回自增前的值。
  2. accumulateAndGet(int, int, IntBinaryOperator): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的IntBinaryOperator参数定义。
  3. getAndDecrement(int): 获取指定索引位置的当前值,并将其自减1。返回自减前的值。
  4. getAndAccumulate(int, int, IntBinaryOperator): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的IntBinaryOperator参数定义。
  5. compareAndSet(int, int, int): 如果指定索引位置的当前值等于预期值(第二个参数),则将其更新为新值(第三个参数)。返回一个布尔值表示是否成功更新。
  6. compareAndSetRaw(long, int, int): 类似于compareAndSet,但使用长整型索引。
  7. addAndGet(int, int): 将指定的增量(第二个参数)添加到指定索引位置的元素上,并返回结果。
  8. checkedByteOffset(int): 检查给定的偏移量是否有效,并返回相应的字节偏移量。
  9. getAndSet(int, int): 获取指定索引位置的当前值,并将其设置为新值(第二个参数)。返回旧值。
  10. byteOffset(int): 返回指定索引位置的字节偏移量。
  11. length(): 返回数组的长度。
  12. get(int): 获取指定索引位置的值。
  13. lazySet(int, int): 设置指定索引位置的值,但不保证立即可见性。
  14. decrementAndGet(int): 获取指定索引位置的当前值,并将其自减1。返回自减前的值。
  15. weakCompareAndSet(int, int, int): 如果指定索引位置的当前值等于预期值(第二个参数),则尝试将其更新为新值(第三个参数)。返回一个布尔值表示是否成功更新。
  16. toString(): 返回数组的字符串表示形式。
  17. set(int, int): 设置指定索引位置的值。
  18. getRaw(long): 获取指定索引位置的值,使用长整型索引。
  19. getAndUpdate(int, IntUnaryOperator): 获取指定索引位置的当前值,并应用给定的一元操作函数(第二个参数)。返回操作后的结果。
  20. incrementAndGet(int): 获取指定索引位置的当前值,并将其自增1。返回自增后的值。
  21. getAndAdd(int, int): 获取指定索引位置的当前值,并将其加上指定的增量(第二个参数)。返回结果。
  22. updateAndGet(int, IntUnaryOperator): 应用给定的一元操作函数(第二个参数)到指定索引位置的元素上,并返回操作后的结果。

AtomicLongArray

提供了一种线程安全的方式来操作long类型的数组。它提供了一系列的原子操作方法,如get、set、compareAndSet等,这些方法可以确保在多线程环境下对数组元素的操作是原子性的。
在这里插入图片描述
类方法说明:

  1. set(int index, long newValue): 将指定索引位置的元素设置为新值。
  2. addAndGet(int index, long delta): 将指定的增量(delta)添加到指定索引位置的元素上,并返回结果。
  3. getAndUpdate(int index, LongUnaryOperator updateFunction): 获取指定索引位置的当前值,应用给定的一元操作函数(updateFunction),并将结果写回该位置,最后返回操作前的值。
  4. getAndDecrement(int index): 获取指定索引位置的当前值,将其自减1,并将结果写回该位置,最后返回操作前的值。
  5. checkedByteOffset(int index): 检查给定的索引是否有效,并返回相应的字节偏移量。
  6. getRaw(long offset): 获取指定偏移量处的元素值。
  7. lazySet(int index, long newValue): 设置指定索引位置的元素值为新值,但不保证立即可见性。
  8. length(): 返回数组的长度。
  9. compareAndSet(int index, long expect, long update): 如果指定索引位置的当前值等于预期值(expect),则将其更新为新值(update)。返回一个布尔值表示是否成功更新。
  10. accumulateAndGet(int index, long x, LongBinaryOperator accumulatorFunction): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的累加器函数(accumulatorFunction)定义。
  11. getAndIncrement(int index): 获取指定索引位置的当前值,并将其自增1,然后将结果写回该位置,最后返回操作前的值。
  12. getAndAccumulate(int index, long x, LongBinaryOperator accumulatorFunction): 对指定索引位置的元素进行累加操作,并返回累加后的结果。累加操作由提供的累加器函数(accumulatorFunction)定义。
  13. getAndAdd(int index, long delta): 获取指定索引位置的当前值,将其加上指定的增量(delta),然后将结果写回该位置,最后返回操作前的值。
  14. updateAndGet(int index, LongUnaryOperator updateFunction): 应用给定的一元操作函数(updateFunction)到指定索引位置的元素上,并返回操作后的结果。
  15. getAndSet(int index, long newValue): 获取指定索引位置的当前值,并将其设置为新值(newValue)。返回旧值。
  16. weakCompareAndSet(int index, long expect, long update): 如果指定索引位置的当前值等于预期值(expect),则尝试将其更新为新值(update)。返回一个布尔值表示是否成功更新。
  17. incrementAndGet(int index): 获取指定索引位置的当前值,将其自增1,然后将结果写回该位置,最后返回操作后的值。
  18. toString(): 返回数组的字符串表示形式。
  19. byteOffset(int index): 返回指定索引位置的字节偏移量。
  20. decrementAndGet(int index): 获取指定索引位置的当前值,将其自减1,然后将结果写回该位置,最后返回操作后的值。
  21. get(int index): 获取指定索引位置的值。
  22. compareAndSetRaw(long offset, long expect, long update): 如果指定偏移量处的当前值等于预期值(expect),则将其更新为新值(update)。返回一个布尔值表示是否成功更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴代庄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值