多线程环境下AtomicInteger计数不符合预期的问题求助
嘿,这个问题我太熟了!你遇到的计数远小于预期的情况,大概率是因为没有让所有线程共享同一个AtomicInteger实例,或者在更新时误用了非原子的操作逻辑。别担心,我给你拆解清楚并给出正确的实现方案~
问题根源
AtomicInteger本身是线程安全的,它的原子方法(比如incrementAndGet())已经帮你处理了竞态条件。但如果你的代码里每个线程都创建了自己的AtomicInteger实例,那每个线程其实都在独立计数,最后汇总的时候自然得不到1000的结果。另外,如果你用了counter.set(counter.get() + 1)这种非原子操作,也会因为多个线程同时读取和写入导致计数丢失。
正确实现思路
要解决这个问题,核心就是两点:
- 让所有线程共享同一个AtomicInteger对象,不能每个线程单独初始化
- 必须使用AtomicInteger提供的原子更新方法,比如
incrementAndGet()、addAndGet(1),这些方法是线程安全的,不会出现计数丢失
示例代码
错误示范(可能是你当前的写法)
import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class WrongCounterDemo { static class TaskThread extends Thread { // 每个线程自己持有计数器实例 private AtomicInteger counter = new AtomicInteger(0); @Override public void run() { for (int i = 0; i < 100; i++) { counter.incrementAndGet(); } } public AtomicInteger getCounter() { return counter; } } public static void main(String[] args) throws InterruptedException { List<TaskThread> threads = new ArrayList<>(); for (int i = 0; i < 10; i++) { threads.add(new TaskThread()); } // 启动线程 for (Thread t : threads) { t.start(); } // 等待所有线程结束 for (Thread t : threads) { t.join(); } // 这里如果只取某一个线程的计数器,结果只会是100,远小于1000 System.out.println("Total count: " + threads.get(0).getCounter().get()); } }
正确实现
import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class CorrectCounterDemo { static class TaskThread extends Thread { // 共享的计数器,通过构造方法传入 private final AtomicInteger sharedCounter; public TaskThread(AtomicInteger sharedCounter) { this.sharedCounter = sharedCounter; } @Override public void run() { for (int i = 0; i < 100; i++) { // 使用原子递增方法,线程安全 sharedCounter.incrementAndGet(); // 如果需要批量增加,比如每次加5,用sharedCounter.addAndGet(5) } } } public static void main(String[] args) throws InterruptedException { // 创建唯一的共享计数器实例 AtomicInteger totalCounter = new AtomicInteger(0); List<TaskThread> threads = new ArrayList<>(); // 给每个线程传入同一个计数器 for (int i = 0; i < 10; i++) { threads.add(new TaskThread(totalCounter)); } // 启动所有线程 for (Thread t : threads) { t.start(); } // 等待所有线程执行完成 for (Thread t : threads) { t.join(); } // 最终结果应该是10*100=1000 System.out.println("Total count: " + totalCounter.get()); } }
额外注意事项
- 永远不要手动实现
get()+set()的递增逻辑,这会破坏原子性,导致竞态条件 - 如果你的计数场景更复杂(比如需要先判断再更新),可以使用AtomicInteger的
compareAndSet()方法来实现复合原子操作 - 除了AtomicInteger,你也可以用
synchronized块来实现线程安全计数,但AtomicInteger在高并发场景下性能更优
内容的提问来源于stack exchange,提问作者LivingRobot
相关产品推荐
相关产品推荐

