Java多线程中原子性操作类怎么用

发布时间:2021-10-31 13:41:13 作者:小新
来源:亿速云 阅读:179
# Java多线程中原子性操作类怎么用

## 目录
1. [原子性操作类概述](#一原子性操作类概述)
2. [基本类型原子类](#二基本类型原子类)
3. [数组类型原子类](#三数组类型原子类)
4. [引用类型原子类](#四引用类型原子类)
5. [字段更新原子类](#五字段更新原子类)
6. [原子类的底层原理](#六原子类的底层原理)
7. [原子类的性能对比](#七原子类的性能对比)
8. [实际应用场景](#八实际应用场景)
9. [常见问题与解决方案](#九常见问题与解决方案)
10. [总结与最佳实践](#十总结与最佳实践)

---

## 一、原子性操作类概述

### 1.1 什么是原子性操作
原子性操作是指不可被中断的一个或一系列操作,这些操作要么全部执行成功,要么全部不执行。

### 1.2 Java中的原子类
Java从JDK 1.5开始提供了`java.util.concurrent.atomic`包,包含以下主要类别:

| 类别            | 典型类                     |
|-----------------|---------------------------|
| 基本类型        | AtomicInteger, AtomicLong |
| 数组类型        | AtomicIntegerArray        |
| 引用类型        | AtomicReference           |
| 字段更新器      | AtomicIntegerFieldUpdater |

### 1.3 与传统同步方式的对比

```java
// 传统方式
private int counter = 0;
public synchronized void increment() {
    counter++;
}

// 原子类方式
private AtomicInteger counter = new AtomicInteger(0);
public void increment() {
    counter.incrementAndGet();
}

优势对比: - 性能更高(无锁或乐观锁) - 代码更简洁 - 避免死锁风险


二、基本类型原子类

2.1 AtomicInteger

核心方法

// 初始化
AtomicInteger atomicInt = new AtomicInteger(0);

// 常用操作
atomicInt.get();           // 获取当前值
atomicInt.set(10);         // 直接设置
atomicInt.compareAndSet(expect, update); // CAS操作
atomicInt.incrementAndGet(); // ++i
atomicInt.getAndIncrement(); // i++

典型应用场景

// 线程安全的计数器
class Counter {
    private AtomicInteger count = new AtomicInteger(0);
    
    public void add() {
        count.incrementAndGet();
    }
    
    public int get() {
        return count.get();
    }
}

2.2 AtomicLong

特殊方法

// 适用于统计场景
AtomicLong counter = new AtomicLong(0);
counter.addAndGet(100);  // 增加指定值
counter.accumulateAndGet(10, (x, y) -> x * y); // 函数式更新

性能优化

JDK 8+推荐使用LongAdder替代高并发写场景:

LongAdder adder = new LongAdder();
adder.increment();
long sum = adder.sum();

三、数组类型原子类

3.1 AtomicIntegerArray

基本使用

// 初始化长度为10的原子数组
AtomicIntegerArray array = new AtomicIntegerArray(10);

// 原子性更新
array.set(0, 100);
array.getAndAdd(0, 5);  // 下标0的元素加5

复合操作示例

// 原子性地将第i个元素更新为newValue
boolean success = array.compareAndSet(i, expect, newValue);

3.2 其他数组类型


四、引用类型原子类

4.1 AtomicReference

对象引用更新

AtomicReference<User> userRef = new AtomicReference<>();
User newUser = new User("Alice");
userRef.set(newUser);

// CAS更新
User oldUser = userRef.get();
User updatedUser = new User("Bob");
userRef.compareAndSet(oldUser, updatedUser);

4.2 AtomicStampedReference(解决ABA问题)

// 初始值和版本号
AtomicStampedReference<String> ref = 
    new AtomicStampedReference<>("init", 0);

// 更新时检查版本
int[] stampHolder = new int[1];
String current = ref.get(stampHolder);
if(ref.compareAndSet(current, "new", stampHolder[0], stampHolder[0]+1)) {
    // 更新成功
}

五、字段更新原子类

5.1 AtomicIntegerFieldUpdater

使用要求

  1. 字段必须是volatile
  2. 必须是实例字段(非static)
  3. 字段修饰符需匹配

示例代码

class MyClass {
    volatile int value;
}

AtomicIntegerFieldUpdater<MyClass> updater = 
    AtomicIntegerFieldUpdater.newUpdater(MyClass.class, "value");

MyClass obj = new MyClass();
updater.set(obj, 10);
updater.incrementAndGet(obj);

六、原子类的底层原理

6.1 CAS机制

Compare-And-Swap核心伪代码:

int compare_and_swap(int* reg, int oldval, int newval) {
    int old_reg_val = *reg;
    if (old_reg_val == oldval)
        *reg = newval;
    return old_reg_val;
}

6.2 Unsafe类

原子类底层依赖sun.misc.Unsafe提供的CAS操作:

public final native boolean compareAndSwapInt(
    Object o, long offset, int expected, int x);

6.3 CPU指令支持

现代CPU提供的原子指令: - x86: CMPXCHG - ARM: LDREX/STREX


七、性能对比

7.1 基准测试数据

JMH测试结果(ops/ms):

实现方式 低并发 高并发
synchronized 1,200 350
AtomicInteger 8,500 6,200
LongAdder 12,000 28,000

7.2 选型建议


八、实际应用场景

8.1 计数器

// 网站访问统计
AtomicLong pageViews = new AtomicLong(0);

void onPageVisit() {
    pageViews.incrementAndGet();
}

8.2 状态标记

// 服务状态管理
AtomicReference<State> state = new AtomicReference<>(State.STOPPED);

boolean start() {
    return state.compareAndSet(State.STOPPED, State.RUNNING);
}

九、常见问题与解决方案

9.1 ABA问题

现象:值从A→B→A,CAS无法感知中间变化
解决方案:使用AtomicStampedReference

9.2 性能瓶颈

现象:高并发时CAS失败率高
解决方案: 1. 改用LongAdder 2. 减小竞争范围(分段锁)


十、总结与最佳实践

10.1 使用原则

  1. 优先使用原子类而非锁
  2. 根据场景选择合适的具体实现
  3. 注意ABA问题和内存一致性

10.2 完整示例

// 线程安全的ID生成器
class IdGenerator {
    private final AtomicLong counter = new AtomicLong(0);
    
    public long nextId() {
        return counter.incrementAndGet();
    }
}

10.3 未来发展方向

”`

推荐阅读:
  1. 怎么在java中利用并发实现原子操作类
  2. Java多线程Atomic包操作原子变量与原子类的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:如何使用Git备份Linux配置文件

下一篇:Mysql数据分组排名实现的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》