CPU 和 线程

9 阅读4分钟

一、CPU 和线程的基本概念

1. 什么是 CPU?

  • **CPU(中央处理器)**是计算机的核心硬件,负责执行所有的计算和指令。
  • 现代服务器通常有多个物理核心(Core),每个核心可以独立处理任务。
  • 有些 CPU 支持超线程(Hyper-Threading) ,一个物理核心可以模拟成两个“逻辑核心”,提升并发能力。

2. 什么是线程?

  • 线程是操作系统调度的最小单位,是程序中实际被 CPU 执行的“工作单元”。
  • 一个进程可以包含多个线程,这些线程可以并发执行。
  • 线程的状态包括:新建(New)、就绪(Ready)、运行(Running)、阻塞/等待(Blocked/Waiting)、终止(Terminated)。

3. 线程与 CPU 的关系

  • 线程需要被 CPU 核心调度执行,一个线程在某一时刻只能被一个核心执行。
  • N核 CPU,同一时刻最多只能有 N 个线程被真正“运行”,其余线程处于等待(就绪)或阻塞状态。
  • 操作系统通过“时间片轮转”让多个线程轮流获得 CPU 执行权,实现“多任务并发”。

二、线程和 CPU 占用的关系

1. 能占用 CPU 的是线程

  • 只有处于“就绪”或“运行”状态的线程才会消耗 CPU。
  • 阻塞/等待状态(如等待 IO、锁、sleep)的线程不会占用 CPU。

2. 线程数和 CPU 占用的关系

  • 线程多≠CPU占用高,关键看有多少线程在“忙碌”地执行。
  • 少量线程如果每个都在高强度计算,也能让 CPU 占用升高。
  • 线程多但大部分在等待(如 IO 阻塞),CPU 占用可能很低。

3. 线程的“就绪”状态

  • 线程已经具备运行条件,只是暂时没有被分配到 CPU。
  • 一旦有空闲核心,调度器会立刻让其运行。

三、什么情况下会导致 CPU 占用升高?

1. 代码层面

  • 死循环或递归:线程陷入无限循环,持续占用 CPU。
  • 高频轮询:频繁轮询数据库、消息队列、外部接口,没有等待或限流。
  • 大量并发请求:短时间内大量请求,线程池满载,CPU 资源被耗尽。
  • 频繁垃圾回收(GC) :内存泄漏或对象创建过多,导致 GC 线程频繁运行。
  • 复杂计算任务:如加密、压缩、大数据处理等。

2. 外部依赖或环境

  • 依赖服务响应慢:调用外部服务超时,线程堆积,CPU 被消耗。
  • 数据库慢查询:数据库响应慢,应用线程等待,间接引发 CPU 飙高。
  • 恶意攻击或爬虫:被恶意流量刷接口,导致 CPU 飙升。

3. 服务器层面

  • 资源竞争:多个进程/服务争抢 CPU。
  • 系统任务异常:如病毒、异常进程等。

四、CPU 100% 时服务的可用性

1. CPU 100% 说明什么?

  • 说明服务器所有 CPU 核心都被占满,系统资源耗尽。
  • 操作系统调度变慢,应用响应变慢甚至无响应。
  • 可能导致请求超时、服务不可用、健康检查失败等。

2. CPU 100% 时服务还可用吗?

  • 理论上,服务还能处理请求,但响应会极慢,用户体验极差。
  • 实际上,大多数情况下服务会出现超时、错误,甚至完全不可用。
  • 健康检查和监控通常会报警,部分云平台会自动重启或下线实例。

3. CPU 100% 服务是不是 down 掉了?

  • 不一定完全 down,但大概率“不可用”或“极不稳定”。
  • 轻则响应慢、超时,重则完全无响应,健康检查失败被摘除。

五、如何排查和优化 CPU 占用高的问题?

  1. 查看线程数和线程状态

    • Linux 下用 tophtopps -efL,或 Java 的 jstack
  2. 分析热点代码

    • 用 Java 的 jstackjvisualvmarthas 等工具分析线程堆栈。
  3. 检查 GC 日志

    • 频繁 GC 也会导致 CPU 高。
  4. 优化代码和架构

    • 避免死循环、合理限流、优化算法、减少不必要的并发。
  5. 扩容或分布式部署

    • 增加服务器或核心数,分散压力。

六、总结

  • CPU 是硬件,线程是操作系统调度的单位。
  • N核 CPU 同时只能执行 N 个线程,其余线程排队等待。
  • CPU 占用高通常是线程“忙碌”导致的,线程多但大部分阻塞不会导致 CPU 高。
  • CPU 100% 时服务大概率不可用或极不稳定,需要及时排查和优化。