为了账号安全,请及时绑定邮箱和手机立即绑定

全局解释锁-GIL

标签:
Python

这几天试了好几种爬虫模式,从单进程到多线程,又试了多进程以及插入协程,纠结于效率问题又了解到GIL,粗浅总结一下不同场景下的多任务模式的选择


先说结论:python多线程鸡肋,多进程好比分布式,协程好比异步IO。


一,GIL及其由来

GIL全称Global Interpreter Lock
官方文档
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.

可以看出:GIL并不是Python的特性,而是CPython解释器,Python完全可以不依赖于GIL,现在很多默认环境就是CPython的Python,GIL的存在更多的是历史原因。

二,作用机制

Python的线程虽然是真正的线程,但解释器执行代码时,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码(为了让各个线程能够平均利用CPU时间,python会计算当前已执行的微代码数量),解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行。

再者,我们都知道线程是共享全局变量的,解决多线程之间数据完整性和状态同步的最简单方法自然也是加锁,那么多锁很容易造成死锁,导致多个线程全部挂起,既不能执行,也无法结束,只能靠操作系统强制终止。

三,python实现多任务

在Python中可以使用多线程,但不要指望能有效利用多核,多线程的并发在Python中就是一个dream。

若一定要通过多线程利用多核,那只能通过C扩展来实现(重写一个不带GIL的解释器),也可以通过多进程实现多核任务,这样还可以防止死锁发生。
单核用多线程的话,如果多任务一旦多到一个限度,会把大量时间用在切换上,就会消耗掉系统所有的资源,结果效率也是急剧下降的。我跟着代码跑了两次,计算密集情况下,发现单线程比多线程效率高了将近20%,

要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数(代码获取核心数multiprocessing.cpu_count( )  ),但是Python这样的脚本语言运行效率很低(这种情况当然C语言最NB)。
在计算任务多但是不大情况下,进程因为创建和调度进程带来的开销要远超出它的正面效应,多线程也需要缓存等等,这个时候就要用到单线程的异步编程模型,也是协程(python的天生优良基因),协程只是单纯的操作CPU的上下文,会大大提高效率。

原文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消