python多线程无法并行cpu密集任务,仅适用于i/o密集场景;需用multiprocessing或processpoolexecutor实现多核并行;主线程结束会导致非守护子线程被强制终止,应调用join()等待或设daemon=true(但会丢失清理操作);print输出可能因缓冲延迟,建议用logging或flush=true;共享可变对象且有写操作时必须用lock,避免竞态条件;queue.queue线程安全,适合生产者-消费者模型,但不持久、不跨进程。

Python 的多线程并不能真正并行 CPU 密集型任务,它只对 I/O 密集型场景有效;想跑满多核,请用 multiprocessing 或 concurrent.futures.ProcessPoolExecutor。
为什么 threading.Thread 启动后看起来没执行?
常见现象是主线程结束、子线程被强制终止——因为 Python 解释器退出时不会等待非守护线程(daemon=False 默认值)完成。
- 确保关键逻辑在子线程中运行完毕:调用
t.join()阻塞主线程,直到t结束 - 若只是“发个请求就不管”,可设
daemon=True,但要注意:进程退出时该线程会直接被杀,日志、清理动作可能丢失 - 不要依赖
print()判断是否执行——I/O 缓冲可能导致输出延迟或乱序,加flush=True或改用logging
threading.Lock 什么时候必须用?
当多个线程共用一个可变对象(如 list、dict、类实例属性),且至少有一个线程会修改它时,就必须加锁。不是“读写才要”,而是“写 + 任意读”就可能出错。
- 典型错误:多个线程同时执行
counter += 1(等价于read → modify → write三步),结果远小于预期 -
Lock是最基础的同步原语,适合短临界区;避免在锁内做 I/O、sleep、调用未知函数——容易卡死其他线程 - 注意锁的粒度:全局一把锁太重,按数据结构分锁(如每个字典 key 对应一个
Lock)更合理,但会增加管理成本
queue.Queue 比手动加锁更安全吗?
是的,queue.Queue 内部已用 threading.Lock 和 threading.Condition 封装好所有操作,线程安全,且自带阻塞/超时机制,适合生产者-消费者模型。
- 不要用普通
list+ 手动append()/pop(0)模拟队列——这不是线程安全的 -
q.get(block=True, timeout=2)可防死等;q.task_done()和q.join()配合能准确等待所有任务处理完 - 注意:
Queue是内存队列,不持久、不跨进程;别把它当 Redis 或 RabbitMQ 用
线程同步真正的难点不在语法,而在厘清“哪些状态被共享”和“哪些操作必须原子”。一个变量被两个线程访问,哪怕只是读,只要另一线程在写,就存在竞态风险——而这种风险往往在高并发或特定调度时机才暴露,调试成本极高。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











