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

多线程 忙等待和线程等待的区别

“忙等待”(Busy Waiting / Spinning)和“线程等待”(Blocking / Sleeping / Yielding)是多线程编程中两种截然不同的等待策略,它们在CPU 资源消耗、响应延迟、适用场景等方面有本质区别。


一、忙等待(Busy Waiting / Spinning)

✅ 定义:

线程在等待某个条件满足时,不放弃 CPU,而是持续循环检查条件(例如反复读取一个标志位),直到条件成立。

🔧 示例(伪代码):

while (!flag) 
{// 空循环,不断检查 flag
}
// 条件满足,继续执行

或使用 SpinLockSpinWait 等:

var sw = new SpinWait();
while (!ready)
{sw.SpinOnce(); // 可能短暂让出或插入 pause 指令
}

⚙️ 特点:

项目说明
CPU 占用高!线程持续占用 CPU 核心
响应延迟极低(纳秒~微秒级),一旦条件满足立刻响应
上下文切换无(不进入内核,不切换线程)
适用场景等待时间极短(如 < 10 微秒)
风险浪费 CPU、可能导致死锁(如在单核 CPU 上)

💡 优化:

现代实现(如 .NET 的 SpinWait)会:

  • 先自旋若干次;
  • 若仍未成功,则调用 Thread.Yield()Thread.Sleep(0) 让出 CPU;
  • 避免在单核系统上完全卡死。

二、线程等待(Blocking / Sleeping)

✅ 定义:

线程在等待时主动放弃 CPU,进入阻塞状态(如等待内核对象信号),由操作系统调度器将其挂起,直到被唤醒。

🔧 示例:

var mre = new ManualResetEvent(false);
mre.WaitOne(); // 线程在此阻塞,不消耗 CPU
// 其他线程调用 mre.Set() 后,本线程被唤醒

其他如:Monitor.Wait()Task.Wait()awaitThread.Sleep() 等。

⚙️ 特点:

项目说明
CPU 占用几乎为 0(线程不运行)
响应延迟较高(微秒~毫秒级),涉及内核切换和调度
上下文切换有(进入内核,线程状态变为 Wait/Sleep)
适用场景等待时间较长或不确定
优势节省 CPU 资源,适合长时间等待

⚠️ 注意:Thread.Sleep()主动休眠,不是“等待条件”,通常不用于同步(应使用事件、信号量等)。


三、核心对比

对比项忙等待(Spinning)线程等待(Blocking)
CPU 使用高(100% 占用一个核心)低(几乎为 0)
延迟极低(无切换开销)较高(10003000 纳秒以上)
是否进入内核否(用户态)是(内核态)
上下文切换
适合等待时间极短(< 几微秒)中到长(> 几十微秒)
典型实现SpinLock, SpinWait, volatile 循环Monitor, AutoResetEvent, Semaphore, await

四、混合策略:自适应等待(Hybrid Lock)

现代高性能锁(如 MonitorSemaphoreSlimManualResetEventSlim)采用混合策略

  1. 先忙等待(自旋若干次)—— 希望在极短时间内获得锁;
  2. 若失败,则转为线程阻塞—— 避免长期浪费 CPU。

例如 .NET 的 lock 语句底层就是混合锁:

  • 先尝试轻量级用户模式同步;
  • 若竞争激烈,则升级为内核事件等待。

五、如何选择?

场景推荐方式
临界区极短(如修改一个字段)忙等待(InterlockedSpinLock
通用互斥访问lock(混合锁)
异步编程SemaphoreSlim.WaitAsync()(非阻塞)
跨线程通知AutoResetEvent / TaskCompletionSource
高性能无锁结构Interlocked + volatile(避免锁)
长时间等待(如 I/O)异步 await,而非任何同步等待

总结一句话:

忙等待 = “盯着看,不走开”;线程等待 = “先去睡觉,叫醒我”
前者快但费电,后者省电但有唤醒延迟。现代系统通常先盯一会儿,再睡觉,取两者之长。

http://www.dtcms.com/a/572708.html

相关文章:

  • 网站建设运维合同汽车城网站建设方案
  • 建立网站需要什么设备网站制作对公司的作用
  • C++类与对象:从入门到精通
  • UniApp 全局通知功能实现
  • uni-app开发安卓app时控制屏幕常亮不息屏
  • uniapp 小程序引入 uview plus 框架,获得精美的UI框架
  • 在被窝里使用笔记本电脑,容易损坏键盘?
  • Unix Domain Socket:构建高效本地进程间通信的完整指南
  • 如何创建“国学助手”GPT?
  • AWS Elastic Beanstalk中安装tesseract5.3.4版本
  • 实战:用Elasticsearch构建爬虫数据搜索引擎
  • 微网站建设及微信公众号长春自助建站软件
  • 修改图片网站卖房app十大排行榜
  • python-爬虫之beautifulsoup
  • Ubuntu 24.04 安装 FreeSWITCH 完整教程
  • LeetCode(python)——49.字母异位词分组
  • Redis 性能优化与故障排查指南
  • 24.java openCV4.x 入门-Imgproc之轮廓凸包与凹陷检测(形状识别)
  • IDEA 插件推荐
  • 虚拟 DOM(Virtual DOM)的工作原理及其性能优化机制
  • git详细使用教程
  • 北京工程工程建设交易信息网站和城乡建设部网站
  • soular零基础学习,如何通过工作台聚合TikLab所有工具链
  • 建立企业网站电商网站建设开题报告
  • css font-size 的妙用
  • Jenkins安装部署
  • 阿里云 CDN + 静态资源(图片 / JS/CSS)缓存优化
  • 荣耀前端开发面试题及参考答案
  • shtml怎么做网站建设学校网站多钱
  • Navicat 连接 SQL Server 报错 [08001] 超时错误(258)的排查与解决方案