You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lambda及新线程中AtomicInteger自增值异常与并行请求完成判断问题

原因分析

这是线程并发执行导致日志输出顺序与实际操作顺序不一致,同时代码存在冗余逻辑:

  1. AtomicInteger本身是线程安全的,无需额外synchronized块:incrementAndGet()是原子操作,加锁完全多余,反而增加线程调度开销,但这不是日志异常的直接原因。
  2. 日志输出与原子操作不构成原子性步骤:
    • Thread-275和Thread-272几乎同时读取到countOfResponse的值为0,先后输出before_inc_count = 0。
    • Thread-275先执行incrementAndGet(),将值从0变为1,但还没来得及输出after_inc_count,Thread-272就已经执行了incrementAndGet(),把值从1变为2。
    • 之后Thread-275才输出after_inc_count = 2,紧接着Thread-272也输出相同值。
    • 本质是读取原子变量、执行自增、输出日志这三个步骤没有被原子化,两个线程的操作交叉执行,导致日志中看不到中间值1。
  3. finally块的判断逻辑存在线程安全问题:多个线程可能同时读取到countOfResponse等于10,导致重复输出完成提示。

正确实现方案

推荐两种可靠的实现方式:

方式1:使用CountDownLatch(最直观)

CountDownLatch专门用于等待一组线程完成任务,逻辑清晰且高效:

CountDownLatch latch = new CountDownLatch(hostInfoList.size());
LOGGER.info("myMethod: hostInfoList_size  = {}", hostInfoList.size());
for (HostInfo hostInfo : hostInfoList) {
    new Thread(() -> {
        ErrorDetails errorDetails = new ErrorDetails();
        XML response = null;
        try {
            LOGGER.info("");
            response = execute_network_request();
        } catch (Exception e) {
            errorDetails.setDetails(e.getMessage());
        } finally {
            LOGGER.info("myMethod: finally");
            latch.countDown();
        }
    }).start();
}
// 阻塞等待所有线程完成
try {
    latch.await();
    LOGGER.info("myMethod: finished all requests");
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

方式2:修正原AtomicInteger逻辑

如果坚持使用AtomicInteger,需确保自增和判断的原子性,同时去掉冗余锁:

AtomicInteger countOfResponse = new AtomicInteger(0);
int totalRequests = hostInfoList.size();
LOGGER.info("myMethod: hostInfoList_size  = {}", totalRequests);
for (HostInfo hostInfo : hostInfoList) {
    new Thread(() -> {
        ErrorDetails errorDetails = new ErrorDetails();
        XML response = null;
        try {
            LOGGER.info("");
            response = execute_network_request();
        } catch (Exception e) {
            errorDetails.setDetails(e.getMessage());
        } finally {
            LOGGER.info("myMethod: finally");
            // 自增后直接判断,确保只有最后一个完成的线程触发提示
            int currentCount = countOfResponse.incrementAndGet();
            if (currentCount == totalRequests) {
                LOGGER.info("myMethod: finished all requests");
            }
        }
    }).start();
}

内容的提问来源于stack exchange,提问作者Alexei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:17:02