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

如何等待其他线程获取锁?不使用Thread.sleep的并发问题解决方案

解决锁获取后的并发等待问题(无需Thread.sleep)

兄弟,这个轮询Thread.sleep()的坑我之前踩过好几次——既浪费CPU资源,还容易因为sleep时长设置不合理导致逻辑延迟或者误判。给你几个优雅的解决方案,完全不用依赖轮询:

方案1:用CountDownLatch实现精准等待

这是最直接的方案,专门用来解决“等待某个/某些操作完成后再继续”的场景:

// 初始化一个计数为1的CountDownLatch,代表我们要等1个事件完成
CountDownLatch latch = new CountDownLatch(1);

acquireLockAndRunOnNewThread(() -> { 
    acquiredLock = true; 
    latch.countDown(); // 锁获取完成后,触发计数减1
    continueWithOtherStuff(); 
});

// 主线程会阻塞在这里,直到latch的计数变为0(也就是锁获取完成)
latch.await(); 

// 现在可以安全执行后续逻辑了
continueWithOtherStuffThatAlsoAcquiresALockAtSomePointInTime();

为什么好用?
await()会让主线程进入高效的阻塞状态,不会像sleep那样空耗CPU;而且只要锁获取完成就会立即唤醒主线程,没有时间精度问题。

方案2:用CompletableFuture简化异步流程(Java 8+)

如果你的项目用Java 8及以上,CompletableFuture能让异步代码更简洁,还自带异常处理能力:

// 将锁获取逻辑包装成异步任务
CompletableFuture<Void> lockTask = CompletableFuture.runAsync(() -> {
    acquiredLock = true;
    continueWithOtherStuff();
});

// 等待异步任务完成(锁获取完成),主线程会阻塞直到任务结束
lockTask.join();

// 执行后续需要锁的逻辑
continueWithOtherStuffThatAlsoAcquiresALockAtSomePointInTime();

额外优势:
如果后续需要处理锁获取失败的异常,可以直接用exceptionally()或者handle()方法,比手动处理线程异常方便得多。

方案3:用Object.wait()/notify()实现原生通知机制

如果你不想引入额外工具类,Java原生的等待/通知机制也能解决问题,但要注意同步块的使用:

final Object waitLock = new Object();
boolean acquiredLock = false;

acquireLockAndRunOnNewThread(() -> { 
    synchronized(waitLock) {
        acquiredLock = true;
        waitLock.notify(); // 通知主线程:锁已经拿到了
    }
    continueWithOtherStuff(); 
});

synchronized(waitLock) {
    // 用while循环防止虚假唤醒,确保确实是锁获取完成才继续
    while (!acquiredLock) {
        waitLock.wait(); // 主线程进入等待,直到被notify唤醒
    }
}

continueWithOtherStuffThatAlsoAcquiresALockAtSomePointInTime();

注意事项:
wait()和notify()必须在同步块内调用,而且一定要用while循环检查条件(不能用if),避免因为JVM的虚假唤醒导致逻辑出错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:13:26