17370845950

Python多线程代码_Python多线程编程示例代码解析
threading.Thread不执行目标函数的主因是target传了函数调用(如my_func())而非函数引用(my_func),且主线程未调用join()导致子线程被终止;CPU密集型任务无加速源于GIL限制,应改用multiprocessing或numpy等绕过GIL的方

案。

为什么 threading.Thread 启动后不执行目标函数?

常见现象是调用了 t.start(),但 target 函数毫无反应。根本原因通常是:把函数调用写成了函数引用 —— 例如传了 target=my_func()(带括号),实际应传 target=my_func(不带括号)。
另一个高频坑是主线程结束太快,子线程被强制终止(尤其在脚本末尾没加 t.join())。Python 的 threading 模块不会自动等待子线程完成。

实操建议:

  • 检查 target 参数是否为函数名本身,而非调用表达式
  • 所有启动的 Thread 实例,若需确保其执行完毕,必须显式调用 .join()
  • 避免在 target 函数中直接修改全局变量而不加锁 —— 即使看起来“只是读”,也可能因字节码交错引发意外

queue.Queue 在多线程间安全传数据,但程序卡死?

典型表现是生产者调用 q.put(item) 后阻塞,或消费者调用 q.get() 后永远等不到数据。这不是队列“坏了”,而是没理解 queue.Queue 的阻塞机制和配套方法语义。

关键点:

  • q.get() 默认阻塞,直到有数据;若确定队列非空,可加 timeout=1 避免无限等待
  • 使用 q.task_done() 必须与 q.join() 配对 —— 每次 get() 后处理完任务,就得调一次 task_done(),否则 join() 永远不会返回
  • q.empty()q.qsize() 在多线程下不可靠,仅作粗略参考,不能用于条件判断逻辑

为什么 CPU 密集型任务用 threading 几乎不提速?

这是 Python 的 GIL(全局解释器锁)导致的硬限制:同一时刻只有一个线程执行 Python 字节码。所以纯计算任务(如循环累加、正则匹配大量文本、数值计算)无法通过多线程并行利用多核。

应对策略取决于场景:

  • 如果任务含 I/O(文件读写、网络请求、数据库查询),threading 依然有效 —— I/O 时 GIL 会释放,其他线程可运行
  • 若确实是 CPU 密集型,改用 multiprocessing 模块,每个进程有独立解释器和 GIL
  • 部分计算可用 numpyscipy 加速 —— 它们的底层 C 实现绕过 GIL,此时多线程也能受益

调试多线程时,print 输出乱序甚至缺失?

不是 bug,是标准输出(sys.stdout)默认行缓冲 + 线程竞争的结果。多个线程同时调 print(),可能把不同线程的字符串碎片混在一起,或因缓冲未刷新而丢失。

临时解决办法(仅限调试):

  • print()flush=True 参数,如 print("msg", flush=True)
  • logging 模块替代 —— 它线程安全,且支持格式化和输出定向
  • 更稳妥的方式是把日志内容先写入线程本地变量或 queue.Queue,由单个线程统一输出

GIL 不保证 print 原子性,这点容易被忽略 —— 即使只 print 一个变量,背后也涉及对象转换、编码、写缓冲多个步骤,中间可能被切换。