大家好,我是正在实战各种 AI 项目的程序员晚枫。
CPython 如何实现多线程?线程状态如何管理?线程间如何通信?这一讲,结合 GIL 深入理解 Python 的多线程机制。
📖 开篇:Python 线程不是操作系统的线程
Python 有自己的线程概念——threading 模块:
1 | import threading |
Python 的 threading.Thread 在 CPython 中底层是操作系统的原生线程(pthread 或 Windows threads),但受 GIL 限制。
🧵 PyThreadState(线程状态)
每个 Python 线程都有一个 PyThreadState 对象:
1 | // Include/pystate.h |
线程状态链表
1 | interp |
🔄 线程调度
GIL + 线程调度 = 协作式调度
1 | 线程 A ──> 执行字节码(持有 GIL) |
线程切换的实际过程
1 | import threading |
原因:counter += 1 其实是 4 条字节码指令,两线程交错执行时会丢失中间结果。
🛡️ 线程同步原语
Lock(互斥锁)
1 | import threading |
RLock(可重入锁)
同一个线程可以多次获取同一把锁:
1 | lock = threading.Lock() |
Semaphore(信号量)
控制同时访问的线程数量:
1 | # 限制最多 5 个线程同时访问 |
📊 线程间通信
Queue(线程安全队列)
1 | import threading |
Event(事件)
1 | import threading |
Condition(条件变量)
用于复杂的线程协调:
1 | import threading |
⚠️ 常见陷阱
陷阱1:守护线程
1 | # 守护线程在主线程结束时会被强制终止 |
陷阱2:死锁
1 | # 循环等待:线程 A 等锁 B,线程 B 等锁 A |
💡 本节作业
- 验证 counter += 1 在多线程下的丢失更新问题
- 用 Lock 修复上述问题
- 用 Queue 实现一个生产者-消费者模式
🎯 本讲总结
PyThreadState:每个 Python 线程的状态对象,包含栈帧、异常状态、GIL 持有状态。
线程调度:GIL 释放 -> 调度器选择 -> GIL 获取 -> 执行,协作式调度。
同步原语:Lock(互斥)、RLock(可重入)、Semaphore(计数信号量)。
线程通信:Queue(队列)、Event(事件)、Condition(条件变量)。
📚 推荐教材
《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》
🔗 课程导航
← 上一讲:GIL 全局解释器锁 | 下一讲:模块导入系统 →
💬 联系我
| 平台 | 账号/链接 |
|---|---|
| 微信 | 扫码加好友 |
| B 站 | Python 自动化办公社区 |
主营业务:AI 编程培训、企业内训、技术咨询