Thread.sleep() 不会释放锁,无论 synchronized 还是 ReentrantLock;它仅使线程进入 TIMED_WAITING 状态并让出 CPU,但锁仍被持有,与会释放锁的 wait() 有本质区别。

Thread.sleep() 不会释放 Runnable 内部的锁,无论锁是通过 synchronized 还是 ReentrantLock 获取的。
sleep 本身不碰锁,只暂停线程
调用 Thread.sleep() 只会让当前线程进入 TIMED_WAITING 状态,主动让出 CPU 时间片,但不会触发任何锁释放动作。它和“休息”一样——人睡着了,手还紧紧攥着钥匙(锁)。
- 如果线程在
synchronized(this)块里调用了sleep(),锁依然被持有,其他线程无法进入同一把锁保护的同步块 - 如果用了
ReentrantLock lock = new ReentrantLock(),且已调用lock.lock(),那么sleep()后锁仍被占着,除非显式调用lock.unlock() - 这种行为与
Object.wait()完全不同:后者必须在同步块内调用,且会立即释放锁
常见误用场景:以为“睡一下就让别人进来”
很多开发者看到线程休眠,下意识觉得“它放手了”,结果导致其他线程无限等待。典型例子:
- 一个线程在
synchronized方法中执行Thread.sleep(2000),另一线程尝试进入同一同步方法,只能阻塞等待,直到第一个线程睡醒并退出同步块 - 日志可能显示:“Thread-0 拿到锁 → 开始 sleep → Thread-1 启动 → Thread-1 尝试拿锁 → 阻塞…” 直到 Thread-0 sleep 结束、退出同步块,Thread-1 才能获取锁
想让锁暂时释放?换 wait 或手动 unlock
如果业务逻辑确实需要“暂停 + 放锁”,不能靠 sleep(),得选对的方法:
立即学习“Java免费学习笔记(深入)”;
- 用
wait():必须在synchronized块内调用,自动释放锁;唤醒后需重新竞争锁 - 用
ReentrantLock的tryLock(long, TimeUnit)或配合Condition实现带超时的等待 - 手动控制:先
unlock(),再sleep(),之后再lock()(注意状态一致性与重入问题)
别忘了处理中断
sleep() 可能被中断,抛出 InterruptedException。捕获后建议:
- 恢复中断状态:
Thread.currentThread().interrupt() - 避免吞掉异常导致上层无法感知中断意图
- 尤其在线程池或长时间运行任务中,忽略中断可能引发资源泄漏或响应迟滞


















