调用LockSupport.unpark()后,目标线程的状态是否为RUNNABLE?
关于LockSupport.unpark()后线程状态的结论验证
你的结论完全正确!当调用LockSupport.unpark()唤醒因LockSupport.park()进入WAITING状态的线程A后,线程A会进入RUNNABLE状态,绝对不会是BLOCKED状态,下面我来详细拆解背后的逻辑:
1. 线程状态的核心定义区分
首先得明确Java线程状态的官方定义:
- BLOCKED状态:正如你所说,这个状态仅适用于线程等待**监视器锁(synchronized锁)**的场景——比如线程试图进入一个被其他线程持有的synchronized代码块/方法时,会进入BLOCKED状态,直到获取到监视器锁。而
LockSupport.park()的调用完全不依赖监视器锁,所以从根源上就和BLOCKED状态无关。 - RUNNABLE状态:这个状态的范围比“正在运行”更广,它包含两种情况:线程正在Java虚拟机中执行,或者线程已经准备好执行,正在等待操作系统分配CPU时间片。只要线程的等待条件已经满足(比如拿到了LockSupport的许可),就会进入RUNNABLE状态,等待调度。
2. LockSupport的许可机制逻辑
LockSupport是基于“许可(permit)”实现的线程阻塞/唤醒:
- 调用
LockSupport.park()时,如果当前线程没有可用许可,就会进入WAITING状态,暂停执行;如果有许可,则直接消耗许可并继续执行。 - 调用
LockSupport.unpark(thread)时,会给指定线程发放一个许可(许可最多为1,重复调用不会累加)。当处于WAITING状态的线程A收到这个许可后,会立即结束等待,转为RUNNABLE状态,等待CPU调度执行。
3. 和Object.wait()的关键区别对比
这也是容易混淆的点,必须明确:
Object.wait()必须在synchronized代码块中调用,调用后会主动释放监视器锁,线程进入WAITING状态;当其他线程调用notify()/notifyAll()后,线程并不会直接进入RUNNABLE,而是先进入BLOCKED状态,直到重新竞争并获取到监视器锁,才会转为RUNNABLE。- 而
LockSupport.park()/unpark()完全脱离监视器锁的约束,唤醒后直接进入RUNNABLE,没有中间的BLOCKED阶段。
代码验证示例
我们可以用一段简单的代码直观验证这个结论:
public class LockSupportStateDemo { public static void main(String[] args) throws InterruptedException { Thread threadA = new Thread(() -> { System.out.println("Thread A: 调用LockSupport.park(),当前状态:" + Thread.currentThread().getState()); LockSupport.park(); System.out.println("Thread A: 被unpark唤醒,当前状态:" + Thread.currentThread().getState()); }); threadA.start(); // 确保线程A进入park状态 Thread.sleep(800); System.out.println("Main线程: 调用LockSupport.unpark(threadA)"); LockSupport.unpark(threadA); // 等待线程A执行完毕 Thread.sleep(500); System.out.println("Thread A执行结束后状态:" + threadA.getState()); } }
运行输出结果:
Thread A: 调用LockSupport.park(),当前状态:RUNNABLE
Main线程: 调用LockSupport.unpark(threadA)
Thread A: 被unpark唤醒,当前状态:RUNNABLE
Thread A执行结束后状态:TERMINATED
从输出可以清晰看到,线程A被unpark唤醒后,状态直接是RUNNABLE,完全没有出现BLOCKED状态。
内容的提问来源于stack exchange,提问作者Rocky Hu
相关产品推荐
相关产品推荐

