为什么线程的sleep时间不准确?

在我们日常编程的过程中,经常会遇到一个问题:线程的sleep时间似乎并不像我们想象的那样准确,比如我们让线程sleep 100ms,实际sleep的时间经常是大于这个时间的。那么,为什么线程的sleep时间不准确呢?让我们来一探究竟。

线程状态:生命周期的五个阶段

首先我们需要了解一下线程的生命周期,线程的生命周期可以分为5个状态:

  1. 新生状态:线程对象被创建出来,但还没有开始运行。想象一下,这就像你买了一台新电脑,但还没有开机启动一样。
  2. 就绪状态:线程已经准备好运行,只是在等待系统分配CPU资源。这就像你已经打开了电脑,程序加载完毕,只等你开始操作一样。
  3. 运行状态:线程正在执行自己的代码,就像你正在使用电脑进行各种操作一样。
  4. 阻塞状态:线程暂时停止执行,等待某些条件满足后再继续运行。这就像你正在玩电脑游戏,突然有人打电话来,你需要暂停游戏去接电话一样。
  5. 死亡状态:线程执行完毕或被强制终止,就像你关闭电脑一样。

Sleep时间不准确的原因

休眠并非即刻醒来

当我们调用线程的sleep方法时,线程会进入阻塞状态,等待指定的时间后再恢复到就绪状态。然而,这个"恢复到就绪状态"并不意味着线程立即就会开始运行,它还需要等待系统分配CPU资源。因此,实际的sleep时间可能会超出我们设定的时间,这就是线程sleep时间不准确的主要原因。

上下文切换的额外消耗

此外,还有一些其他因素也会影响线程sleep的准确性,例如上下文切换的开销。每次线程切换,都需要保存当前线程的状态(例如寄存器的值、执行的地址空间等)并加载新线程的状态,这个过程是需要时间的。同时,CPU缓存中的数据也可能因为线程切换而失效,从而导致CPU需要从内存中重新读取数据,这也会增加额外的时间开销。

线程的调度:谁先运行

上面我们提到线程就绪后等待系统分配CPU资源是sleep时间超出的主要原因。那么,系统是如何决定哪个线程应该获得CPU资源的呢?这就涉及到了线程调度的问题。

线程调度是操作系统中的一项重要功能,其目标是使系统的运行尽可能高效。线程调度需要考虑的因素很多,包括用户需求(例如响应时间、周转时间等)、系统需求(例如吞吐量、CPU利用率等)、线程的优先级、资源平衡等。

在实际的线程调度中,往往需要在不同的需求之间做出权衡。例如,如果我们希望系统的响应时间尽可能小,那么就需要频繁地进行线程切换;但是,线程切换会带来额外的开销,从而降低系统的吞吐量和CPU利用率。这就像我们在玩游戏和接电话之间做出选择一样,无论我们选择哪一个,都需要牺牲另一个,而且选择之后还要想想刚才进行到哪里了。

如何做出决策

线程调度的时机通常在操作系统内核对中断/异常/系统调用处理后返回到用户态时。例如:

  • 当你正在使用文本编辑器写作时,突然移动了鼠标,操作系统就需要处理这个鼠标移动的中断,处理完毕后可能就会切换到其他线程,如音乐播放器线程。
  • 你的浏览器线程在运行过程中出现了异常,操作系统处理完异常后,可能会切换到其他正常运行的线程,如邮件客户端线程。
  • 你的下载线程请求读取硬盘文件,操作系统在处理完这个系统调用后,可能会切换到其他线程,如视频播放线程。

具体的调度算法根据操作系统的不同而不同,例如UNIX使用的是动态优先数算法,Linux使用的是抢占式算法(CFS完全公平调度算法),而Windows使用的是基于动态优先级的抢占式多任务调度。这些算法的细节这里就不赘述了,有兴趣的可以去查询一下。


总的来说,线程的sleep时间不准确主要是由于线程调度和上下文切换的开销导致的。在实际的编程中,我们需要意识到这一点,避免过度依赖sleep的准确性。

关注微/信/公/众/号:萤火架构,提升技术不迷路。

相关推荐
weixin_408099677 分钟前
【实战对比】在线 OCR 识别 vs OCR API 接口:从个人工具到系统集成该怎么选?
图像处理·人工智能·后端·ocr·api·图片文字识别·文字识别ocr
穿条秋裤到处跑1 小时前
每日一道leetcode(2026.03.31):字典序最小的生成字符串
算法·leetcode
Victor3562 小时前
MongoDB(73)如何设置用户权限?
后端
Victor3562 小时前
MongoDB(74)什么是数据库级别和集合级别的访问控制?
后端
计算机学姐2 小时前
基于SpringBoot的咖啡店管理系统【个性化推荐+数据可视化统计+配送信息】
java·vue.js·spring boot·后端·mysql·信息可视化·tomcat
LSTM973 小时前
使用 Python 将图片转换为 PDF (含合并)
后端
小江的记录本3 小时前
【注解】常见 Java 注解系统性知识体系总结(附《全方位对比表》+ 思维导图)
java·前端·spring boot·后端·spring·mybatis·web
小飞Coding3 小时前
MyBatis Mapper 实现原理彻底解密——从动态代理到 JDBC 执行全链路剖析
后端·mybatis
Mr.45673 小时前
Spring Boot 集成 PostgreSQL 表级备份与恢复实战
java·spring boot·后端·postgresql
LucianaiB3 小时前
王炸组合!腾讯云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!
后端