"唉, 还没毕业就受到甲方的支配, 等以后进了公司可咋整啊." 小白嘴里这么吐槽, 但心理上还是不敢怠慢, 只能恋恋不舍地关掉眼前的游戏, 打开了 Python 代码思考了起来.
"现在的程序是单线程的, 那就用多线程模型来优化吧, 嘿嘿, 我太机智了!" 小白打心底感谢前段时间里学习到的线程的知识."Python 里好像是 threading 模块负责多线程的, 就决定是你了, threading !"
花了两三个小时, 小白终于把程序改好了, 他长舒一口气, 点击 Run , 开始测试运行时间.
"woc! 怎么运行时间还变长了?" 看着屏幕上显示的测试结果, 小白傻眼了, 这多线程怎么不顶用? 自己明明是按官方文档来的啊!
debug 无果, 小白只好寻求好朋友小明的帮助.
- "哈哈哈, 你居然用 python 的多线程? 你不知道 python 的多线程被很多人称作「鸡肋」吗?"
- "啊, 不会吧? 还有这种说法? 我要是知道我肯定就不用多线程来改了... 可为什么 python 的多线程就鸡肋了? 那多线程爬虫是怎么回事?"
- "我先给你解释下 python 下的多线程是怎么一回事吧. Python 是一门解释型语言, 它的执行是由解释器来控制的, 我们一般都会使用默认的 Cpython 解释器, 这些我想你应该清楚."
- "那当然, 这在一开始学 Python 的时候老师就讲过了."
"那你知不知道什么是 GIL?" 小明问道.
小白挠挠头, 尴尬的回答:"我没听说过."
- "也是, 你要是知道 GIL , 就能弄明白 Python 的多线程了. GIL, 全称是 Global Interpreter Lock , 全局解释锁 , 专门给解释器用的."
- "蛤? 解释器还要需要锁?"
- "这个锁别有妙用, 让我先考考你, C 语言能不能在用户态下做到线程级别的时间片轮转?"
"不能! 操作系统里讲过了, 我还记得上次你教我的内容~" 小白得意的回答.
关于线程, 详细的在这里: https://www.cnblogs.com/tobe98/p/11651237.html
- "但是 python 能做到! python 里, 解释器可以记录每一个线程执行了多长时间 -- 时间一到, 就能够切换到另一条线程."
- "有点意思, 听起来像是解释器充当了操作系统的角色, 然后为 python 线程提供了时间片轮转的能力."
tobe 注: 理论上 C 语言也可以做到, 毕竟 python 解释器就是用 C 语言写的.
"解释的很到位, 我再说回 GIL 吧, 在多核还没有出现的时候, 就已经有线程的存在了, GIL 就是拿来给线程加锁的, 当一个线程将要执行时, 解释器会把 GIL 锁给这个线程, 其他线程因为没有锁, 是无法运行的. 等到持有锁线程阻塞或者运行 100 个字节码, 解释器就会把锁交给其他线程."
"但是这个 GIL 锁是全局 (Global) 的, 也就导致即使是多核情况下, 一次也只有一个线程能运行, 从整体上看, 整个程序是串行的."
小白恍然大悟:"怪不得我的程序还变慢了, 原来 python 的多线程不仅不能利用多核, 还因为线程切换拖慢了我程序的执行速度! 我想很多人应该都遇到过我这个问题吧, Python 社区为什么不修改这一特性, 让多线程也做到并行呢?"
小明叹了口气:"哪有这么简单, 修改锁的设计是很难的, 我听说 MYSQL 拆分 buffer pool mutex 这个全局锁花了好多年呢. 不过 Python 社区为此还是做了不少挽救工作的, 比如在线程睡觉(sleep), 等待连接的时候主动释放 GIL, 让其他线程继续执行. 拿爬虫程序来说吧, 单个爬虫总会花时间在下载网页上, 很多 CPU 时间就浪费掉了, 提供 sleep 机制后, 这些爬虫可以在等待下载时释放 GIL 锁, 把机会让给其他爬虫, 这样整体运行速度能够得到大幅提升."
"我好像明白了," 小白感觉自己被打通了任督二脉:"也就是说 Python 的多线程适合 I/O 密集型的程序, 但是对计算密集型程序就不那么友好了~ 诶等等, 那我怎么办? 我还打算用多线程优化我的程序呢!"
"让 python 利用多核的方法还是有的, 比如说, 让 python 调用 C 语言的代码, 在 C 语言里实现多线程, 因为 C 语言里没有 GIL 锁, 这些线程不会受到 GIL 的约束, 也就能并行了."
小白一个劲儿摇头:"不不不不不, 好不容易写完的 Python 代码, 你让我改成 C? 这不是要我的命吗! 我拒绝!"
- "这不是还有第二种方法嘛 -- 使用多进程, Python 里有个 multiprocessing 模块, 可以创建多个进程, 因为不同的进程使用不同的解释器, 所以它们有各自的 GIL, 互不干扰, 自然就能完成并发了."
- "这个方法听起来才正常嘛, 我马上就回去试试, 谢谢你了!"
希望你在看完我的文章之后有所收获~(求点赞呐!)
来源: https://www.cnblogs.com/tobe98/p/11773961.html