当前位置: 首页 > news >正文

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

文章目录

    • 一、先说结论:BLOCKED vs WAITING 核心对比
    • 二、BLOCKED:想进门但门锁了
    • 三、WAITING:主动说"我先歇着"
    • 四、一个场景看清两种状态
    • 五、容易忽略的 TIMED_WAITING
    • BLOCKED 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"#12prio=5os_prio=0tid=0x...state=BLOCKED-waitingtolock<0x000000076b5c0a80>// 等待这把锁 👈-locked<0x000000076b5c0b90>

三、WAITING:主动说"我先歇着"

线程主动放弃执行权,进入 WAITING 状态,等待另一个线程显式唤醒它:

方法触发唤醒
Object.wait()释放锁,进入等待notify()/notifyAll()
Thread.join()等目标线程结束目标线程执行完毕
LockSupport.park()阻塞当前线程LockSupport.unpark(thread)

关键点:WAITING 的线程可能已经拿到过锁,但主动释放了

synchronized(lock){while(!condition){lock.wait();// 释放锁,进入 WAITING 👈}// 被 notify 唤醒后,重新获取锁,继续执行}

生活类比:你在银行办业务,发现材料不全,主动说"我先到旁边等,材料到了叫我"——这就是 WAITING。你曾经坐在柜台前(持有锁),但主动让出来了。

四、一个场景看清两种状态

Objectlock=newObject();// 线程 A:先拿到锁,然后 waitThreadA=newThread(()->{synchronized(lock){try{lock.wait();// A 释放锁 → 进入 WAITING 👈}catch(InterruptedExceptione){}}});// 线程 B:想获取锁ThreadB=newThread(()->{synchronized(lock){// A 还在 wait,B 可以获取锁lock.notify();// 唤醒 A 👈}});

时间线:

  1. A 获取锁 → A 执行 wait() → A 释放锁 →A 进入 WAITING
  2. B 获取锁 → B 执行 notify() → B 释放锁
  3. 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 是拿到锁后主动释放。

加分回答
  1. 和 Lock 体系的关系:ReentrantLock 的 lock() 等待不是 BLOCKED,而是 WAITING(底层调用 LockSupport.park())。只有 synchronized 才会产生 BLOCKED 状态,这是面试中的高频混淆点
  2. notify 后不是直接运行:wait() 的线程被 notify 后,不会立即执行,而是要先重新竞争锁——如果竞争失败,会从 WAITING 变成 BLOCKED。所以唤醒 ≠ 运行
  3. 实战排查:线上大量 BLOCKED 通常意味着锁竞争激烈(慢查询、死锁等),大量 WAITING 可能是线程池空闲或条件等待。jstack 是区分这两种状态的最佳工具
面试官点评

这道题考的是你对线程状态流转的精确理解。能分清 BLOCKED 和 WAITING 只是及格线,能说出"notify 后先竞争锁再运行"、"ReentrantLock 等待是 WAITING 不是 BLOCKED"这些细节,面试官才知道你是真排查过线上问题的。状态流转理解透了,并发问题的诊断能力就上了一个台阶。

原文阅读


内容有帮助?点赞、收藏、关注三连!评论区等你 💪

http://www.jsqmd.com/news/729641/

相关文章:

  • 宇宙学模拟中CGD建模的挑战与改进方法
  • Nmap使用详解
  • FastQ/BAM降采样深度对比:Picard三大策略 vs Samtools,你的大数据场景该选谁?
  • MTKClient刷机工具终极指南:联发科设备救砖与刷机完整解决方案
  • project_travel_advisor高级功能实现:地理位置、数据筛选和响应式设计
  • 普通人如何利用GPT赚钱之提供咨询服务
  • 2026晶圆测厚传感器哪家强:电极片测厚传感器、透明物体测厚传感器、非接触式传感器、高精度激光位移传感器、高精度激光测距仪选择指南 - 优质品牌商家
  • 基于Next.js与Chakra UI的AI聊天应用模板开发实践
  • 电子制造追溯系统:技术架构与质量管理实践
  • 大模型驯化秘籍: Harness工程如何让AI从玩具变生产力?
  • 合法网络安全研究:渗透测试与安全监控工具开发
  • STM32串口接收中断避坑指南:标准库的USART1_IRQHandler与HAL库的HAL_UART_IRQHandler到底怎么选?
  • 在QNX中运行PTPD实现gPTP同步问题的排查与解决
  • 安全带 安全绳 检测数据集】 数据集共有2000张;
  • 语音转文本与机器翻译系统中合成数据的可靠性研究
  • 2026崇州物流托盘技术解析:崇州环保托盘生产厂家/崇州设备木箱包装/崇州货运托盘/崇州重型托盘/崇州重型木箱包装/选择指南 - 优质品牌商家
  • 为什么 LinkedBlockingQueue 并发性能这么强?一文吃透双锁机制
  • project_travel_advisor:如何使用Google地图和React构建终极旅行助手应用
  • 保姆级教程:在RTX 3090上从零部署MIT-BEVFusion(附CUDA-BEVFusion完整配置流程)
  • 时间序列模型选型指南:AR、MA、ARMA、ARIMA到底该用哪个?看完这篇不再纠结
  • WSL2里的Arch太久没更新?一招解决pacman签名错误,告别invalid or corrupted package
  • linux下手工安装ollama0.9.6
  • 开源免费的WPS AI 软件 察元AI文档助手:链路 020:runPlainDocumentAssistantExecution 单次 chatCompletion
  • ARM原子操作指令解析:LDSETP与LDSMAX实战指南
  • 保姆级教程:在Ubuntu 20.04上从零部署PointPillars ROS节点(含CUDA 11.7/Spconv 2.x避坑指南)
  • 别再为覆盖率头疼了!聊聊Test Point如何帮你搞定ATPG Pattern数量
  • 终极Fabric物品与方块API开发指南:从零开始创建自定义游戏元素的完整流程
  • 如何选择最佳Mac应用清理工具:Pearcleaner 2025年完整使用指南
  • Fuel Core 终极商业模式解析:区块链基础设施的可持续盈利探索
  • Ollamac本地AI对话伴侣:隐私优先的图形化大模型客户端部署与实战