Java并发15:原子类AtomicXXX详解 - 无锁的线程安全

引言:volatile不能保证原子性 回顾之前讲过的例子: public class Counter { private volatile int count = 0; public void increment() { count++; // 不是原子操作! } } 问题: count++; // 实际上是3个操作: // 1. temp = count (读) // 2. temp = temp + 1 (修改) // 3. count = temp (写) // 多线程执行时可能丢失更新 解决方案1:synchronized public synchronized void increment() { count++; // 原子操作 } // 缺点:性能开销大 解决方案2:原子类 private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); // 原子操作,性能好 } 性能对比: synchronized: 1200ms AtomicInteger: 280ms 性能提升: 4.3倍 本篇文章将深入Java原子类的实现原理和使用方法。 ...

2025-11-20 · maneng

无锁编程与LongAdder:高并发计数器的性能优化

一、AtomicLong的性能瓶颈 1.1 高并发下的问题 // 1000个线程,每个线程累加100万次 AtomicLong counter = new AtomicLong(0); ExecutorService executor = Executors.newFixedThreadPool(1000); for (int i = 0; i < 1000; i++) { executor.submit(() -> { for (int j = 0; j < 1_000_000; j++) { counter.incrementAndGet(); // CAS操作 } }); } // 耗时:约 15秒(高并发场景) 性能瓶颈: CAS自旋:高并发时,CAS失败率高,大量自旋消耗CPU 缓存失效:所有线程竞争同一个变量,导致CPU缓存频繁失效(Cache Line伪共享) 串行化:本质上是串行执行,无法充分利用多核CPU 1.2 LongAdder的解决方案 // 同样的场景,使用LongAdder LongAdder counter = new LongAdder(); ExecutorService executor = Executors.newFixedThreadPool(1000); for (int i = 0; i < 1000; i++) { executor.submit(() -> { for (int j = 0; j < 1_000_000; j++) { counter.increment(); // 分段累加 } }); } long result = counter.sum(); // 最终求和 // 耗时:约 2秒(高并发场景) // 性能提升:约 7.5倍! 为什么更快? ...

2025-11-19 · maneng

并发工具类与原子操作:无锁编程的艺术

引子:一个计数器的性能优化之路 在前两篇文章中,我们学习了synchronized和Lock来保证线程安全。但是,锁总是有性能开销的。有没有不用锁就能保证线程安全的方法?答案是:CAS(Compare-And-Swap)+ 原子类。 场景:网站访问计数器 /** * 方案1:使用synchronized(加锁) */ public class SynchronizedCounter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } } /** * 方案2:使用AtomicInteger(无锁) */ public class AtomicCounter { private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); // 无锁,基于CAS } public int getCount() { return count.get(); } } // 性能对比测试 public class CounterBenchmark { private static final int THREAD_COUNT = 100; private static final int ITERATIONS = 10000; public static void main(String[] args) throws InterruptedException { // 测试synchronized版本 SynchronizedCounter syncCounter = new SynchronizedCounter(); long syncTime = testCounter(() -> syncCounter.increment()); System.out.println("Synchronized耗时:" + syncTime + "ms"); // 测试AtomicInteger版本 AtomicCounter atomicCounter = new AtomicCounter(); long atomicTime = testCounter(() -> atomicCounter.increment()); System.out.println("AtomicInteger耗时:" + atomicTime + "ms"); System.out.println("性能提升:" + (syncTime * 100.0 / atomicTime - 100) + "%"); } private static long testCounter(Runnable task) throws InterruptedException { Thread[] threads = new Thread[THREAD_COUNT]; long start = System.currentTimeMillis(); for (int i = 0; i < THREAD_COUNT; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < ITERATIONS; j++) { task.run(); } }); } for (Thread t : threads) t.start(); for (Thread t : threads) t.join(); return System.currentTimeMillis() - start; } } /* 执行结果(JDK 8, 4核CPU): Synchronized耗时:856ms AtomicInteger耗时:342ms 性能提升:150% 为什么AtomicInteger更快? 1. 无锁,避免线程阻塞和上下文切换 2. 基于CPU的CAS指令,硬件级支持 3. 自旋重试,适合竞争不激烈的场景 但是,AtomicInteger不是万能的: ├─ 竞争激烈时,自旋会浪费CPU ├─ 不适合复杂的原子操作 └─ 需要理解CAS的原理和限制 */ 本文将深入探讨CAS的原理、Atomic类的实现、以及常用的并发工具类。 ...

2025-11-03 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...