越狱模拟器:挖掘免安装绿色中文版
6.2G · 2025-10-31
Java中的Atomic类是java.util.concurrent.atomic包提供的一组线程安全操作类,它们通过CAS(Compare-And-Swap)机制实现无锁的线程安全编程,在高并发场景下比传统的synchronized和Lock具有更好的性能表现。本文将全面解析Atomic类的核心原理、常用类及其方法,并通过实战案例展示其应用场景。
在多线程环境中,简单的操作如i++并非原子性,会导致竞态条件问题。传统解决方案是使用synchronized关键字,但synchronized是一种悲观锁,存在性能开销大、容易死锁等问题。
Java从JDK 1.5开始提供了java.util.concurrent.atomic包,通过CAS操作实现了无锁算法,无需加锁就能保证线程安全,大幅提升了并发性能。
Atomic类的核心实现基于CPU硬件提供的CAS指令。CAS操作包含三个操作数:内存位置(V)、预期原值(A)和新值(B)。当且仅当V的值等于A时,才会将V的值更新为B,否则不执行任何操作。
CAS是一种乐观锁策略,其工作流程为:
// CAS操作伪代码
public boolean compareAndSwap(int value, int expect, int update) {
    if(value == expect) {
        value = update;
        return true;
    }
    return false;
}
优势:
局限性:
Java的Atomic类可分为五大类,覆盖基本类型、数组、引用对象、字段更新等场景:
对int类型进行原子操作,常用方法:
incrementAndGet():自增1,返回新值(类似++i)getAndIncrement():自增1,返回旧值(类似i++)addAndGet(int delta):增加指定值,返回新值compareAndSet(int expect, int update):CAS更新对long类型进行原子操作,方法与AtomicInteger类似
对布尔值进行原子操作,常用方法:
get():获取当前布尔值set(boolean newValue):设置布尔值compareAndSet(boolean expect, boolean update):CAS更新对引用类型进行原子操作,常用方法:
get():获取当前引用set(V newValue):设置新引用compareAndSet(V expect, V update):CAS更新引用带版本号的引用原子操作,解决ABA问题,常用方法:
getReference():获取当前引用值getStamp():获取当前版本号compareAndSet(V expectReference, V newReference, int expectStamp, int newStamp):同时比较引用和版本号带布尔标记的引用原子操作,与AtomicStampedReference类似,但用布尔值标记是否被修改
对int数组元素进行原子操作,常用方法:
get(int index):获取指定索引的值set(int index, int newValue):设置指定索引的值compareAndSet(int index, int expect, int update):CAS更新数组元素分别用于原子更新long数组和对象引用数组,用法类似
基于反射机制,原子更新对象的volatile int字段,无需修改原有类结构
分别用于更新long字段和对象字段
高并发场景下的累加优化,通过分段累加减少竞争
支持自定义累加函数的高效累加器
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter {
    private AtomicInteger counter = new AtomicInteger(0);
    
    public void increment() {
        counter.incrementAndGet();
    }
    
    public int getCount() {
        return counter.get();
    }
    
    public static void main(String[] args) throws InterruptedException {
        AtomicCounter atomicCounter = new AtomicCounter();
        
        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                atomicCounter.increment();
            }
        };
        
        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        
        System.out.println("最终计数: " + atomicCounter.getCount()); // 输出2000
    }
}
import java.util.concurrent.atomic.AtomicBoolean;
public class SafeFlag {
    private AtomicBoolean flag = new AtomicBoolean(false);
    
    public void startTask() {
        if (flag.compareAndSet(false, true)) {
            System.out.println("任务开始执行");
            // 执行任务逻辑
        } else {
            System.out.println("任务已在执行中");
        }
    }
    
    public void stopTask() {
        flag.set(false);
    }
}
import java.util.concurrent.atomic.AtomicReference;
public class ConcurrentStack<E> {
    private AtomicReference<Node<E>> top = new AtomicReference<>();
    
    private static class Node<E> {
        public final E item;
        public Node<E> next;
        
        public Node(E item) {
            this.item = item;
        }
    }
    
    public void push(E item) {
        Node<E> newHead = new Node<>(item);
        Node<E> oldHead;
        do {
            oldHead = top.get();
            newHead.next = oldHead;
        } while (!top.compareAndSet(oldHead, newHead));
    }
    
    public E pop() {
        Node<E> oldHead;
        Node<E> newHead;
        do {
            oldHead = top.get();
            if (oldHead == null) {
                return null;
            }
            newHead = oldHead.next;
        } while (!top.compareAndSet(oldHead, newHead));
        return oldHead.item;
    }
}
import java.util.concurrent.atomic.AtomicStampedReference;
public class ABASolution {
    private AtomicStampedReference<Integer> atomicStampedRef = 
            new AtomicStampedReference<>(100, 0);
    
    public void transfer(int amount) {
        int[] stampHolder = new int[1];
        int current = atomicStampedRef.get(stampHolder);
        int newStamp = stampHolder[0] + 1;
        
        while (!atomicStampedRef.compareAndSet(current, current + amount, 
                                             stampHolder[0], newStamp)) {
            current = atomicStampedRef.get(stampHolder);
        }
    }
}
在高并发场景下,Atomic类通常比synchronized快2-3倍,但在高竞争环境下优势可能减小。对于高并发的累加操作,LongAdder比AtomicLong性能更好。
ABA问题解决方案:
// 使用AtomicStampedReference解决ABA问题
AtomicStampedReference<Integer> asr = new AtomicStampedReference<>(100, 0);
// 更新时同时检查值和版本号
int[] stampHolder = new int[1];
int current = asr.get(stampHolder);
asr.compareAndSet(current, newValue, stampHolder[0], stampHolder[0] + 1);
高竞争环境优化:
// 使用LongAdder替代AtomicLong
LongAdder adder = new LongAdder();
// 多线程并发增加
adder.increment();
// 获取最终结果
long sum = adder.sum();
Java的Atomic类通过CAS机制提供了一种高效的线程安全解决方案,特别适用于计数器、状态标志、引用更新等场景。相比传统锁机制,Atomic类具有更好的性能表现,但也存在ABA问题、自旋开销等局限性。在实际开发中,应根据具体场景选择合适的Atomic类,并注意其适用边界。
对于简单原子操作,优先考虑Atomic类;对于高并发累加场景,使用LongAdder;对于需要检测值变化的场景,使用带版本号或标记的引用类;对于复杂操作,仍需结合锁机制。合理选择并发工具是编写高效、安全并发程序的关键。
 
                    