基本类型原子类

原子基本类型
  • AtomicInteger:整型原子类
  • AtomicLong:长整型原子类
  • AtomicBoolean :布尔型原子类

上面三个类提供的方法几乎相同,所以这里以 AtomicInteger 为例子来介绍。

AtomicInteger 类常用方法

public final int get();  // 获取当前的值

public final int getAndSet(int newValue);  // 获取当前的值,并设置新的值

public final int getAndIncrement();  // 获取当前的值,并自增

public final int getAndDecrement();  // 获取当前的值,并自减

public final int getAndAdd(int delta);  // 获取当前的值,并加上预期的值

boolean compareAndSet(int expect, int update);  // 如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update)

public final void lazySet(int newValue);  // 最终设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值
AtomicInteger 常见方法使用
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int temvalue = 0;
        AtomicInteger i = new AtomicInteger(0);
        temvalue = i.getAndSet(3);
        System.out.println("temvalue:" + temvalue + ";  i:" + i);  // temvalue:0;  i:3
        temvalue = i.getAndIncrement();
        System.out.println("temvalue:" + temvalue + ";  i:" + i);  // temvalue:3;  i:4
        temvalue = i.getAndAdd(5);
        System.out.println("temvalue:" + temvalue + ";  i:" + i);  // temvalue:4;  i:9
    }

}
基本数据类型原子类的优势

通过一个简单例子看一下基本数据类型原子类的优势。

① 多线程环境不使用原子类保证线程安全(基本数据类型)

class Test {

        private volatile int count = 0;

        // 若要线程安全执行执行count++,需要加锁
        public synchronized void increment() {
            count++; 
        }

        public int getCount() {
            return count;
        }
}

② 多线程环境使用原子类保证线程安全(基本数据类型)

class Test2 {

        private AtomicInteger count = new AtomicInteger();

        public void increment() {
            count.incrementAndGet();
        }

        // 使用AtomicInteger之后,不需要加锁,也可以实现线程安全。
        public int getCount() {
            return count.get();
        }
}

AtomicInteger 线程安全原理简单分析

AtomicInteger 类的部分源码:

    // setup to use Unsafe.compareAndSwapInt for updates(更新操作时提供“比较并替换”的作用)
    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); }
    }

    private volatile int value;

AtomicInteger 类主要利用 CAS (compare and swap) + volatilenative 方法来保证原子操作,从而避免 synchronized 的高开销,执行效率大为提升。

CAS 的原理是拿期望的值和原本的一个值作比较,如果相同则更新成新的值。UnSafe 类的 objectFieldOffset() 方法是一个本地方法,这个方法是用来拿到“原来的值”的内存地址。另外 value 是一个 volatile 变量,在内存中可见,因此 JVM 可以保证任何时刻任何线程总能拿到该变量的最新值。

<think>好的,用户想了解Java原子的使用方法及原理。首先,我需要回忆一下原子基本概念。根据引用[4],原子具有原子性,确保一组操作要么全部成功,要么全部失败,似于锁但可能有更好的性能优势。 接下来,用户可能想知道具体有哪些原子。根据引用[1],atomic包下有16个原子,分为基本类型、数组类型、引用类型等。需要举例说明,比如AtomicInteger,AtomicLongArray等,并给出代码示例,这样用户能更直观地理解使用方法。 然后,原理部分。引用[3]提到,像num++这样的操作不是原子的,而原子通过CAS(比较并交换)操作实现原子性。需要解释CAS的工作原理,以及它如何避免锁的开销,提升性能。可能还要提到Unsafe的使用,但要注意用户是否需要深入底层。 使用方法方面,用户可能需要知道如何初始化原子,常用方法如get()、set()、getAndIncrement()等。例如,AtomicInteger的incrementAndGet()方法代替i++,确保线程安全。代码示例会帮助用户理解如何在实际中使用。 另外,引用[2]指出原子可以替代synchronized来处理非原子操作,比如i++。这里需要比较原子和锁的优缺点,引用[4]提到原子相对于锁的优势,比如更轻量,减少线程阻塞。 可能还要提到原子的局限性,比如ABA问题,以及如何用AtomicStampedReference解决。这部分需要简明扼要,避免让用户感到困惑。 最后,生成相关问题时要覆盖原理、使用场景、与锁的比较、ABA问题等,确保用户能全面了解原子的各个方面。</think>### Java原子使用方法及原理分步解析 #### 一、基本使用方法 Java原子通过`java.util.concurrent.atomic`包提供线程安全的数值操作,典型使用场景如下: 1. **基本类型原子** ```java AtomicInteger count = new AtomicInteger(0); // 原子自增 count.incrementAndGet(); // 相当于i++ // 原子比较并交换 boolean success = count.compareAndSet(0, 1); // 当前值为0时更新为1 ``` 2. **数组原子** ```java AtomicIntegerArray array = new AtomicIntegerArray(10); array.set(0, 100); // 线程安全地设置数组元素 array.getAndAdd(0, 5); // 索引0元素+5 ``` #### 二、实现原理 1. **CAS(Compare And Swap)机制** - 通过`Unsafe`实现硬件级别的原子操作 - 操作步骤: - 读取当前值$V_1$ - 计算目标值$V_2 = V_1 + \Delta$ - 当且仅当内存值仍为$V_1$时更新为$V_2$ - 伪代码表示: $$ \text{CAS}(V_1, V_2) = \begin{cases} \text{true} & \text{if } \text{内存值} = V_1 \\ \text{false} & \text{otherwise} \end{cases} $$ [^3] 2. **与锁的对比优势** - 无阻塞算法:失败线程可立即重试 - 减少线程上下文切换 - 适合低竞争场景(高竞争时可能产生大量自旋)[^4] #### 三、典型源码分析(以AtomicInteger为例) ```java public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } // Unsafe实现 public final int getAndAddInt(Object o, long offset, int delta) { int v; do { v = getIntVolatile(o, offset); } while (!compareAndSwapInt(o, offset, v, v + delta)); return v; } ``` 此代码展示了典型的CAS自旋模式,通过循环尝试保证原子性更新[^3]。 #### 四、注意事项 1. **ABA问题** - 使用`AtomicStampedReference`添加版本号解决 - 示例: ```java AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0); int stamp = ref.getStamp(); ref.compareAndSet(100, 200, stamp, stamp+1); ``` 2. **适用场景** - 计数器、状态标志等简单原子操作 - 替代`synchronized`的轻量级并发控制[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值