讲师中心 微信公众号
AI工具推荐 视频效率加速

如何减少线程上下文切换_无锁编程、CAS与合理配置线程池容量

雨芳同学_6315

雨芳同学_6315

发布时间:2026-02-24 18:18:11

|

655人浏览过

|

来源于php中文网

原创

线程池过大导致性能下降的主因是上下文切换开销激增。当线程数远超CPU核心数,频繁切换(1–5μs/次)吞噬大量CPU时间,吞吐不升反降;需据任务类型(CPU/I/O密集)合理设定线程数,避免盲目扩容。

如何减少线程上下文切换_无锁编程、cas与合理配置线程池容量

为什么线程池设太大反而更慢

线程数超过 CPU 核心数太多时,上下文切换开销会吃掉大量 CPU 时间,实际吞吐不升反降。这不是理论,是 perf stat -e context-switches 能直接观测到的现象。

  • Java 默认的 Executors.newCachedThreadPool() 无限扩容,高并发下可能瞬间创建数百线程,切换成本爆炸
  • Go 的 goroutine 虽轻量,但调度器在系统线程(M)不足时仍会阻塞,GOMAXPROCS 设太小或太大都影响调度效率
  • Python 的 concurrent.futures.ThreadPoolExecutor 若 max_workers 设为 os.cpu_count() * 5,I/O 密集场景尚可,CPU 密集型任务基本是在给调度器添堵

CAS 不是万能锁替代品,用错地方照样卡死

无锁编程靠 compareAndSet(Java)、__atomic_compare_exchange(C/C++)或 atomic.CompareAndSwapInt64(Go)实现,但只适合极简状态变更——比如计数器、标志位、单链表头插。一旦涉及多字段协同更新,ABA 问题或重试风暴立刻浮现。

  • Java 中对 AtomicReference 存对象引用,若对象内部字段被多线程修改,CAS 本身不保证该对象的线程安全
  • Go 的 atomic.Value 只支持整体替换,不能做 value.field++ 这类操作;强行用 unsafe.Pointer + CAS 操作结构体字段,极易因内存对齐或编译器重排出错
  • Redis 的 INCR 是原子的,但用 GET + INCR + SET 模拟 CAS 就是典型错误——中间状态完全暴露,必须改用 INCR 或 EVAL 脚本

线程池容量怎么算:分清楚是 CPU 密集还是 I/O 密集

没有银弹公式,但有两个锚点:CPU 核心数和平均阻塞时间。关键不是“最大并发数”,而是“让 CPU 尽量不空转也不过载”。

  • CPU 密集型(如图像处理、加密计算):threadCount ≈ CPU核心数 + 1,+1 是为了弥补偶尔的页缺失或缓存未命中导致的短暂停顿
  • I/O 密集型(如 HTTP 请求、数据库查询):用 threadCount ≈ CPU核心数 × (1 + 平均等待时间 / 平均工作时间),例如等待 90ms、工作 10ms,就是 ×10;但上限建议不超过 200,避免调度失衡
  • Java ForkJoinPool 默认并行度是 Runtime.getRuntime().availableProcessors(),它专为拆分-合并任务设计,别拿它跑 DB 查询

上下文切换开销到底有多大

一次完整上下文切换(保存寄存器 + 切换栈 + TLB 刷新 + 恢复)在现代 x86 上通常耗时 1–5 μs。看起来不多?但每秒切 100 万次,就占掉 1–5 个核的全部时间。

  • vmstat 1 看 cs(context switch)列,持续 > 50k/s 就得警惕;结合 pidstat -w 找具体进程
  • Java 应用里频繁调用 Thread.sleep(1) 或 Object.wait() 且唤醒密集,会触发内核态休眠/唤醒路径,比纯用户态自旋更重
  • Linux 的 /proc/sys/kernel/sched_latency_ns 控制调度周期,默认 6ms;如果线程数远超该周期内能调度的线程量,就会强制压缩每个线程的时间片,加剧切换频率

事情说清了就结束。真正难的不是套公式,是搞清你那段代码——它到底在等磁盘、等网卡、等锁,还是真正在烧 CPU。

相关文章

编程速学教程(入门课程)
编程速学教程(入门课程)

编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

相关专题

更多
switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

1071

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

1437

2024.03.13

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

5034

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

5211

2025.07.04

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6347

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2668

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4498

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

1249

2025.12.24

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn