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

如何使用AtomicInteger改写synchronized修饰的余额原子增减操作方法

正确的AtomicInteger实现方案

首先修改balance的定义:

private AtomicInteger balance = new AtomicInteger(0); // 初始余额可按实际业务需求设置

重写后的完整executeRequest方法:

public void executeRequest(Request request) {
    int amount = request.getAmount();
    switch (request.getType()) {
        case CREDIT:
            int currentBalance;
            // 循环尝试扣款,直到CAS成功或者明确余额不足
            while (true) {
                currentBalance = balance.get();
                // 先判断余额是否足够
                if (currentBalance < amount) {
                    // 余额不足直接失败,无需重试
                    System.out.printf(FAILURE,
                            request,
                            Thread.currentThread().getName(),
                            currentBalance);
                    break;
                }
                int newBalance = currentBalance - amount;
                // 尝试原子更新
                if (balance.compareAndSet(currentBalance, newBalance)) {
                    // CAS成功才打印成功结果
                    System.out.printf(SUCCESS,
                            request,
                            Thread.currentThread().getName(),
                            newBalance);
                    break;
                }
                // CAS失败说明余额被其他线程修改,进入下一轮循环重新判断
            }
            break;
        case REPAYMENT:
            // 还款无前置判断,直接调用原子加法即可,返回更新后的余额
            int newBalance = balance.addAndGet(amount);
            System.out.printf(SUCCESS,
                    request,
                    Thread.currentThread().getName(),
                    newBalance);
            break;
    }
}
原错误实现的问题说明

你之前的写法存在两个核心问题:

  • 把打印逻辑放在了CAS操作之前,且没有区分判断结果就直接进入CAS重试,一旦CAS失败进入下一轮循环,会重复执行打印逻辑,导致异常输出。
  • 没有在余额不足的场景直接终止循环,哪怕余额已经不够,仍然会尝试CAS和重试,做了很多无用操作,而且无法正确终止流程。
实现逻辑说明
  • 扣款逻辑中,我们将「余额判断」和「CAS更新」放在同一个循环体内,每次CAS失败重试时,都会重新读取最新的余额做判断,完全避免了判断条件过时的问题。
  • 只有余额不足或者CAS更新成功两个场景才会跳出循环,保证每一次请求只会输出一次成功/失败日志,和原synchronized实现的行为完全一致。
  • 还款操作因为只需要做加法,不需要前置判断,直接调用AtomicInteger自带的addAndGet原子方法即可,不需要额外写CAS循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 16:54:02