ReentrantLock疑问:无线程调用时无法获锁,线程调用为何可行?
两个Condition测试程序的差异解析
这两个程序的核心差异完全在于执行锁操作和Condition等待/通知的线程归属,咱们一步步拆解清楚:
第一个程序:单线程阻塞导致逻辑卡死
先看第一个程序的核心执行流程:
public static void main(String[] args) throws InterruptedException { ThreadTest2 test = new ThreadTest2(); test.conditionWait(); // 主线程直接执行此方法 Thread.sleep(2000); test.conditionSignal(); }
当主线程调用conditionWait()时,它会先通过lock.lock()获取锁,打印"1",然后调用condition.await()。这里要注意:await()方法会让当前线程释放锁并进入等待状态,但问题是——conditionWait()是在主线程里执行的,await()会直接阻塞主线程,导致conditionWait()方法根本没执行完!
也就是说,主线程卡在condition.await()这一步,后面的Thread.sleep(2000)和test.conditionSignal()代码完全没有机会运行。所以程序只会打印"1",然后一直处于等待状态,永远等不到唤醒信号。
第二个程序:多线程协作实现正常等待/通知
第二个程序把等待和通知的逻辑都放到了独立的子线程中:
- 调用
conditionWait()时,会启动一个新线程A,线程A负责获取锁、打印"1"、调用await()释放锁并进入等待; - 主线程调用完
conditionWait()后不会被阻塞,继续执行Thread.sleep(2000),随后调用conditionSignal()启动另一个新线程B; - 线程B此时能顺利获取锁(因为线程A已经通过
await()释放了锁),打印"3",调用signal()唤醒线程A,接着打印"4",最后释放锁; - 线程A被唤醒后,重新获取锁,打印"2",最终释放锁。
这就是为什么第二个程序的输出是1 3 4 2——两个独立线程完成了基于Condition的标准等待/通知协作流程。
核心差异总结
- 第一个程序:等待逻辑和后续的通知逻辑绑定在同一个主线程中,等待操作阻塞了主线程,导致通知代码永远无法执行;
- 第二个程序:等待和通知逻辑分别在两个独立的线程中执行,等待线程释放锁后,通知线程可以正常获取锁并发送唤醒信号,完成协作。
内容的提问来源于stack exchange,提问作者gesanri
相关产品推荐
相关产品推荐

