关于 Python GIL锁的讨论

写在前面:
先讲两个概念:

  • 并发:多个任务交替执行,当任务一遇到阻塞或者时间片用完将其挂起,切换到任务二区执行。从宏观上来看也是多核任务“同时”执行。
  • 并行:多任务同时执行,在多核心 CPU 时间,多个任务在多核 CPU 核心上同时执行。

Global Interpreter Lock 的前世今生

谈到多进程/多线程,数据安全是不可忽略的。而在 Python 的设计之初,计算机大多是单核的,多线程实际上是并发执行,GIL 的存在对效率影响不大。同时还方便保证了数据安全。

时至今日,我们的计算机处理器四核心、八核心、十六核心乃至更多。这时候因为 GIL 的存在限制了多线程在多核处理器上的运行效率。但是那为什么不直接去掉它?国外有个哥们曾写了一个取消 GIL 的分支,其中为了保证数据安全而不得不加 Luck,经测试下来执行效率并不理想。所以 GIL 一直存在到了现在。

Python 中的多线程是如何工作的?

首先呢,要先知道 GIL 是跟着进程走的,我们的代码是运行在一个进程上。

当你在这个进程中启动了多个线程时,这些线程任务都进入队列等待调度。当CPU的其中一个核心(我们暂时叫他核心1)调度到任一线程任务后(我们叫它任务1),加GIL锁然后执行任务。当这时,如果其他任一CPU核心调度到剩下的任一任务时,会先去检查 GIL,这是 GIL 可能存在两种状态:

  • GIL 被锁:放弃执行重新放回队列中去
  • GIL 已被释放:对 GIL 加锁,然后执行

所以说在同一个 GIL 锁的所有线程在任一时刻,永远只有一个在执行状态,GIL 限制了多线程的效率。

那多线程真的就一无是处了吗?

Python 多线程真的一无是处了吗?

在我们日常所写的代码可以分为计算密级型、IO 密集型。我们分开讨论:

  • 计算密集型:当多线程中的任一任务时间片用完后会释放 GIL 锁,这时包括该任务在内的所有任务会进行 GIL 竞争(谁拿到谁执行),而所有任务都是拿到执行权后立即执行,不存在等待时间(网络、IO)。这样来回切换浪费资源与时间(线程调度也是需要资源与时间的)。我们把这种称为 ****
  • 对 IO 密集型:当在任务执行过程中,如果遇到等待 IO 会直接让出其执行权,执行其他任务。这时候使用多线程对性能是有提升的。

所以,Python 多线程虽然很“鸡肋”,但是对 IO 密集型任务比较友好的。
简单理解下来,可以总结为两句话:

  • 因为时间片用完而切换任务多线程不利,反而会降低效率
  • 因阻塞切换的任务使用多线程可以有利

在我们的日常开发中可以酌情使用。如果真的为了更好的利用多核心 CPU 性能,还是比较推荐直接使用多进程来操作,这样 GIL 锁相互独立,就可以真正实现并行喽~。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值