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

Spring Boot异步场景下如何用Lock实现单例执行refresh逻辑?

问题解决:用ReentrantLock实现单次refresh+多线程等待逻辑

ReentrantLock完全可以解决你遇到的问题,实现起来也不复杂,核心是通过锁控制refresh的执行权限,配合可见性标记避免重复执行,具体方案如下:

实现思路

  • 用ReentrantLock保证同一时间只有一个线程能进入refresh的执行判断逻辑;
  • 用volatile修饰标记位,确保多线程间能实时感知refresh是否完成;
  • 双重检查标记位:仅当refresh未执行时,让首个线程执行refresh,后续线程直接跳过。

代码实现

@Service
@RequiredArgsConstructor
public class TestService {

    private final TestClient client;
    private final TestManager manager;
    private final ReentrantLock refreshLock = new ReentrantLock();
    // volatile保证标记位的多线程可见性
    private volatile boolean refreshCompleted = false;

    @Async
    public void execute() {
        // 替换成你的具体条件判断逻辑
        if (needRefresh()) { 
            try {
                refreshLock.lock();
                // 双重检查:仅当未刷新过时才执行refresh
                if (!refreshCompleted) {
                    manager.refresh();
                    refreshCompleted = true;
                }
            } finally {
                // 必须在finally中释放锁,避免异常导致锁泄漏
                refreshLock.unlock();
            }
        }
        // 所有线程最终都会执行send
        client.send();
    }

    // 可选:如果后续需要重新触发refresh,添加重置标记的方法
    public void resetRefreshStatus() {
        try {
            refreshLock.lock();
            refreshCompleted = false;
        } finally {
            refreshLock.unlock();
        }
    }

    // 替换成你的实际条件判断逻辑
    private boolean needRefresh() {
        // 示例:比如根据配置或业务状态判断是否需要刷新
        return true;
    }
}

逻辑说明

  1. 首个满足条件的线程进入execute方法后,获取锁并检查标记位,发现未刷新则执行manager.refresh(),完成后将标记设为true,最后释放锁;
  2. 后续满足条件的线程会被锁阻塞,直到首个线程释放锁;拿到锁后检查标记位已为true,直接跳过refresh逻辑,释放锁后执行client.send();
  3. volatile修饰的标记位确保所有线程能实时看到最新状态,避免线程缓存旧值导致误判;
  4. 锁在finally块中释放,避免因refresh()抛出异常导致锁无法释放的问题。

额外说明

如果你的业务场景中refresh不是一次性的(比如后续某个时机需要再次触发),可以调用resetRefreshStatus()方法重置标记位,下次满足条件时会重新执行refresh逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 10:33:32