孤舟笔记 并发篇十七 BLOCKED和WAITING两种线程状态有什么区别?面试官想看你对线程生命周期理解多深

张开发
2026/5/1 4:52:28 15 分钟阅读

分享文章

孤舟笔记 并发篇十七 BLOCKED和WAITING两种线程状态有什么区别?面试官想看你对线程生命周期理解多深
文章目录一、先说结论BLOCKED vs WAITING 核心对比二、BLOCKED想进门但门锁了三、WAITING主动说我先歇着四、一个场景看清两种状态五、容易忽略的 TIMED_WAITINGBLOCKED vs WAITING 全景回答技巧与点评标准回答加分回答面试官点评个人网站用 jstack 排查线程问题你一定见过 BLOCKED 和 WAITING 这两种状态。但你真的分得清吗面试官最爱追问“都是线程停下来了它俩到底有啥区别什么时候进入 BLOCKED什么时候进入 WAITING”傻傻分不清的话排查线上问题就是一场噩梦。今天咱们把它俩彻底拆开。一、先说结论BLOCKED vs WAITING 核心对比维度BLOCKEDWAITING含义等待获取锁等待被其他线程显式唤醒触发条件进入 synchronized 锁失败Object.wait()、Thread.join()、LockSupport.park()唤醒条件锁被释放竞争成功被其他线程 notify/signal 或 unpark是否持有锁不持有还没拿到曾经持有已释放CPU 消耗不消耗操作系统调度不消耗操作系统调度生活类比在门外排队等厕所在休息区等人叫号一句话记住BLOCKED 是门被锁了进不去WAITING 是事情没办好主动等着——一个是被动堵一个是主动等。二、BLOCKED想进门但门锁了当线程尝试进入一个被其他线程持有的synchronized块时就进入 BLOCKED 状态synchronized(lock){// 线程 A 持有锁在执行// 线程 B 想进来 → BLOCKED }关键点BLOCKED 的线程从来没拿到过锁。它在门外等着等持锁线程释放后重新竞争。生活类比你去上公厕门锁着有人你站在门口等——这就是 BLOCKED。你没进去过一直在门外。// jstack 中的表现Thread-B#12prio5os_prio0tid0x...stateBLOCKED-waitingtolock0x000000076b5c0a80// 等待这把锁 -locked0x000000076b5c0b90三、WAITING主动说我先歇着线程主动放弃执行权进入 WAITING 状态等待另一个线程显式唤醒它方法触发唤醒Object.wait()释放锁进入等待notify()/notifyAll()Thread.join()等目标线程结束目标线程执行完毕LockSupport.park()阻塞当前线程LockSupport.unpark(thread)关键点WAITING 的线程可能已经拿到过锁但主动释放了。synchronized(lock){while(!condition){lock.wait();// 释放锁进入 WAITING }// 被 notify 唤醒后重新获取锁继续执行}生活类比你在银行办业务发现材料不全主动说我先到旁边等材料到了叫我——这就是 WAITING。你曾经坐在柜台前持有锁但主动让出来了。四、一个场景看清两种状态ObjectlocknewObject();// 线程 A先拿到锁然后 waitThreadAnewThread(()-{synchronized(lock){try{lock.wait();// A 释放锁 → 进入 WAITING }catch(InterruptedExceptione){}}});// 线程 B想获取锁ThreadBnewThread(()-{synchronized(lock){// A 还在 waitB 可以获取锁lock.notify();// 唤醒 A }});时间线A 获取锁 → A 执行 wait() → A 释放锁 →A 进入 WAITINGB 获取锁 → B 执行 notify() → B 释放锁A 被唤醒 → 重新竞争锁 → 如果锁被别人占了 →A 进入 BLOCKED同一个线程 A先 WAITING 后 BLOCKED——先等通知再等锁。五、容易忽略的 TIMED_WAITING还有一种状态不得不提TIMED_WAITING就是带闹钟的等待Thread.sleep(1000);// 1 秒后自动醒来lock.wait(1000);// 1 秒后自动醒来Thread.join(1000);// 等 1 秒LockSupport.parkNanos(1000000000);// 等 1 秒和 WAITING 的唯一区别有个超时闹钟到点自动醒不用别人叫。三种停着的状态总结状态等什么谁来唤醒BLOCKED等锁锁释放 竞争成功WAITING等通知其他线程显式唤醒TIMED_WAITING等通知或超时其他线程唤醒 或 超时自动醒BLOCKED vs WAITING 全景线程停着的状态全景 BLOCKED被动堵 ├── 触发synchronized 锁获取失败 ├── 特征从未持有锁 └── 唤醒锁释放后竞争成功 WAITING主动等 ├── 触发wait() / join() / park() ├── 特征曾经持有锁已释放 └── 唤醒notify / signal / unpark TIMED_WAITING定时等 ├── 触发sleep(n) / wait(n) / join(n) / parkNanos(n) └── 唤醒被唤醒 或 超时自动醒 区分口诀 BLOCKED 门没进等锁是关键 WAITING 主动歇等人才醒来 TIMED 加闹钟到点自动走。回答技巧与点评标准回答BLOCKED 是线程尝试获取 synchronized 锁失败后的状态它从未持有锁等待锁释放后重新竞争。WAITING 是线程主动调用 wait()、join()、park() 后进入的状态它会释放已持有的锁等待其他线程显式唤醒。核心区别BLOCKED 是被动等锁WAITING 是主动等通知BLOCKED 从没拿到锁WAITING 是拿到锁后主动释放。加分回答和 Lock 体系的关系ReentrantLock 的 lock() 等待不是 BLOCKED而是 WAITING底层调用 LockSupport.park()。只有 synchronized 才会产生 BLOCKED 状态这是面试中的高频混淆点notify 后不是直接运行wait() 的线程被 notify 后不会立即执行而是要先重新竞争锁——如果竞争失败会从 WAITING 变成 BLOCKED。所以唤醒 ≠ 运行实战排查线上大量 BLOCKED 通常意味着锁竞争激烈慢查询、死锁等大量 WAITING 可能是线程池空闲或条件等待。jstack 是区分这两种状态的最佳工具面试官点评这道题考的是你对线程状态流转的精确理解。能分清 BLOCKED 和 WAITING 只是及格线能说出notify 后先竞争锁再运行、ReentrantLock 等待是 WAITING 不是 BLOCKED这些细节面试官才知道你是真排查过线上问题的。状态流转理解透了并发问题的诊断能力就上了一个台阶。原文阅读内容有帮助点赞、收藏、关注三连评论区等你

更多文章