跳转到内容

原子类应用

来自代码酷

模板:Note

原子类应用[编辑 | 编辑源代码]

原子类(Atomic Classes)是Java并发编程中提供的一组线程安全工具,用于在不使用锁的情况下实现原子性操作。它们通过硬件级别的CAS(Compare-And-Swap)指令实现高效的无锁并发控制。

核心原理[编辑 | 编辑源代码]

原子类的实现基于以下两个关键机制:

  • volatile变量:保证内存可见性
  • CAS操作:通过
    Unsafe
    
    类调用CPU原子指令

flowchart LR A[线程A读取值] --> B[CAS尝试修改] C[线程B读取值] --> D[CAS尝试修改] B -->|成功| E[更新值] D -->|失败| F[重试操作]

主要原子类[编辑 | 编辑源代码]

Java提供多种原子类,可分为四类:

基本类型[编辑 | 编辑源代码]

  • AtomicBoolean
    
  • AtomicInteger
    
  • AtomicLong
    

数组类型[编辑 | 编辑源代码]

  • AtomicIntegerArray
    
  • AtomicLongArray
    
  • AtomicReferenceArray
    

引用类型[编辑 | 编辑源代码]

  • AtomicReference
    
  • AtomicStampedReference
    
    (解决ABA问题)
  • AtomicMarkableReference
    

字段更新器[编辑 | 编辑源代码]

  • AtomicIntegerFieldUpdater
    
  • AtomicLongFieldUpdater
    
  • AtomicReferenceFieldUpdater
    

代码示例[编辑 | 编辑源代码]

计数器实现[编辑 | 编辑源代码]

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicCounter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet(); // 原子性+1操作
    }

    public int getCount() {
        return count.get();
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicCounter counter = new AtomicCounter();
        
        // 创建100个线程并发增加计数器
        Thread[] threads = new Thread[100];
        for (int i = 0; i < 100; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    counter.increment();
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread t : threads) {
            t.join();
        }
        
        System.out.println("Final count: " + counter.getCount());
        // 输出: Final count: 100000
    }
}

复杂CAS操作[编辑 | 编辑源代码]

AtomicInteger atomicInt = new AtomicInteger(100);

// 只有当当前值为100时才更新为200
boolean success = atomicInt.compareAndSet(100, 200);
System.out.println("Update success: " + success + ", new value: " + atomicInt.get());

// 尝试更新失败示例
success = atomicInt.compareAndSet(100, 300);
System.out.println("Update success: " + success + ", current value: " + atomicInt.get());

/* 输出:
Update success: true, new value: 200
Update success: false, current value: 200
*/

性能对比[编辑 | 编辑源代码]

下表展示不同实现方式的性能差异(单位:纳秒/操作):

实现方式 10线程 100线程
synchronized 120 950
ReentrantLock 85 620
AtomicInteger 15 130

实际应用场景[编辑 | 编辑源代码]

场景1:全局唯一ID生成[编辑 | 编辑源代码]

class IdGenerator {
    private AtomicLong id = new AtomicLong(0);
    
    public long nextId() {
        return id.getAndIncrement();
    }
}

场景2:状态标志控制[编辑 | 编辑源代码]

class TaskRunner {
    private AtomicBoolean running = new AtomicBoolean(false);
    
    public void start() {
        if (running.compareAndSet(false, true)) {
            // 启动任务
        }
    }
    
    public void stop() {
        running.set(false);
    }
}

场景3:高效统计[编辑 | 编辑源代码]

class Statistics {
    private AtomicIntegerArray hourCounts = new AtomicIntegerArray(24);
    
    public void record(int hour) {
        hourCounts.getAndIncrement(hour % 24);
    }
}

高级特性[编辑 | 编辑源代码]

原子累加器[编辑 | 编辑源代码]

Java 8引入更高效的

LongAdder

DoubleAdder

,适用于高并发统计场景:

import java.util.concurrent.atomic.LongAdder;

LongAdder adder = new LongAdder();
// 多线程并发调用
adder.add(5);
adder.increment();
System.out.println(adder.sum()); // 获取当前总和

原子引用更新[编辑 | 编辑源代码]

解决ABA问题的

AtomicStampedReference

示例:

AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);

int[] stampHolder = new int[1];
String current = ref.get(stampHolder); // 同时获取值和版本戳

// 只有当值和版本戳都匹配时才更新
ref.compareAndSet(current, "B", stampHolder[0], stampHolder[0]+1);

数学原理[编辑 | 编辑源代码]

CAS操作的数学表示为: CAS(V,E,N)={V=N如果 V==E无操作其他情况 其中:

  • V = 内存中的变量值
  • E = 预期值
  • N = 新值

最佳实践[编辑 | 编辑源代码]

  • 优先使用原子类替代synchronized
  • 对于简单操作(如计数器)使用基本原子类
  • 高并发统计场景使用
    LongAdder
    
  • 引用类型更新注意ABA问题
  • 避免过度依赖
    getAndSet
    
    ,可能丢失中间状态

页面模块:Message box/ambox.css没有内容。