原子类应用
外观
原子类应用[编辑 | 编辑源代码]
原子类(Atomic Classes)是Java并发编程中提供的一组线程安全工具,用于在不使用锁的情况下实现原子性操作。它们通过硬件级别的CAS(Compare-And-Swap)指令实现高效的无锁并发控制。
核心原理[编辑 | 编辑源代码]
原子类的实现基于以下两个关键机制:
- volatile变量:保证内存可见性
- CAS操作:通过类调用CPU原子指令
Unsafe
主要原子类[编辑 | 编辑源代码]
Java提供多种原子类,可分为四类:
基本类型[编辑 | 编辑源代码]
AtomicBoolean
AtomicInteger
AtomicLong
数组类型[编辑 | 编辑源代码]
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
引用类型[编辑 | 编辑源代码]
AtomicReference
- (解决ABA问题)
AtomicStampedReference
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操作的数学表示为: 其中:
- V = 内存中的变量值
- E = 预期值
- N = 新值
最佳实践[编辑 | 编辑源代码]
- 优先使用原子类替代synchronized
- 对于简单操作(如计数器)使用基本原子类
- 高并发统计场景使用
LongAdder
- 引用类型更新注意ABA问题
- 避免过度依赖,可能丢失中间状态
getAndSet
页面模块:Message box/ambox.css没有内容。
原子类不保证多个操作的原子性,复合操作仍需外部同步 |