IO密集型任务、计算密集型任务,以及Gil锁机制

发布于:2024-06-16 ⋅ 阅读:(28) ⋅ 点赞:(0)

I/O密集型任务、计算密集型任务,以及Gil锁机制

为什么计算密集型用多进程,I/O密集型用多线程

首先记住一点,多进程的资源消耗是远大于线程的

  • 大量的I/O等待期间CPU都是空闲状态,因此对资源的利用率非常低,俗称占着茅坑不拉屎,因此开辟线程更加充分利用资源,也不会因为有大型的计算导致内存崩溃
  • 计算密集型对CPU的运算能力要求较高,通常不是单线程能满足的,因此需要整个进程为其进行处理

当然以上都是基于cpython的,因为python有gil锁的缘故,所以才会有多进程的概念,实际上在正常情况下多进程有明显的资源浪费问题,多线程在效率和资源利用率上明显优于多进程

Gil锁机制(Global Interpreter Lock)

GIL锁是CPython解释器中的一个互斥锁,也叫全局解释器锁,用于防止多个线程同时执行Python字节码。保证同一进程下只有一个线程能够执行Python代码,并操作Python对象

为什么要有Gil锁?

  1. 多线程会被垃圾回收影响,比如线程1刚取消一个对象的引用,但是线程2也要对该对象进行调用,但是就在线程2调用该对象的前一刻被引用计数标记为0,那么就会出现数据安全问题
  2. 当年只有单核cpu,即使开了多线程也只有一个线程在运行,因此作者强加了gil锁

影响

  1. CPU密集型任务受限:对于CPU密集型任务,由于GIL的存在,多线程并不能有效地提高性能,因为多个线程无法同时执行Python字节码
  2. IO密集型任务相对不受限:在IO密集型任务中,线程在等待IO时会释放GIL,允许其他线程执行Python字节码,因此在这种情况下,多线程能够发挥一定作用

示例

CPU密集型任务

当使用ThreadPoolExecutor运行脚本时,即使开了多线程也不会达到预期的执行效率,因为Gil锁在同一时间段内只允许单线程运算,因此在python中使用多线程执行CPU密集型任务时多半是无效的,反之多进程不受影响

假如一个计算密集型的任务需要 10s 的执行时间,总共有4个这样的任务

多进程: 需要开启 4 个进程,但是 4 个 CPU 并行,最终只需要消耗 10s 多一点的时间。

多线程: 只需要开1 个进程,这个进程开启 4 个线程,开启线程所消耗的资源很少,但是由于最终执行是只有一个 CPU 可以工作,所以最终消耗 40s 多的时间。

I/O密集型

假如是多个 IO密集型 的任务 (例如input(),time.sleep())CPU 大多数时间是处于闲置状态,频繁的切换

多进程: 进程进行切换需要消耗大量资源

多线程: 线程进行切换并不需要消耗大量资源,即使有GIL锁的存在,最终也会以量取胜多进程