python之GIL锁


一、GIL锁是什么?

定义:

       GIL:又叫全局解释器锁,是一个互斥锁,每个线程在执行的过程中都需要先获取GIL,保证同一时刻只有一个线程在运行。

原因:

       它并不是python语言的特性,仅仅是由于历史的原因在CPython解释器中难以移除,因为python语言运行环境大部分默认在CPython解释器中。

目的:

       解决多线程同时竞争程序中的全局变量而出现的线程安全问题。

总结:

       1、GIL 不是 Python 的特点,而是 CPython 解释器的特点;

       2、GIL 锁是加在 CPython 解释器上的,是保证解释器级别的数据的安全;

       3、GIL 锁会导致同一个进程下多个线程的不能同时执行;

       4、不同的数据除了 GIL 锁,还需要一把互斥锁,来保证数据处理不会错乱。

       每个线程在调用 cpython 解释器 在运行之前,需要先抢到 GIL 锁,然后才能运行。

编译型语言就不会存在 GIL 锁,编译型语言会直接编译所有代码,就不会出现这种问题。

二、CPython对线程安全的内存管理机制

Python使用引用计数来进行内存管理,在Python中创建的对象都会有引用计数,来记录有多少个指针指向它。当引用计数的值为0时,就会自动释放内存

缺陷:

如果有2个python线程同时引用同一个对象,那么2个线程都会尝试对其进行数据操作,多个线程同时对一个数据进行增加或减少的操作,如果发生这种情况,则可能导致内存泄漏

三、解决GIL问题的方案:

1.使用其它语言,例如C,Java
2.使用其它解释器,如java的解释器jython
3.使用多进程

线程1在CPU1上运行,线程2在CPU2上运行。GIL是全局的,CPU2上的线程2需要等待CPU1上的线程1让出GIL锁,才有可能执行。如果在多次竞争中,线程1都胜出,线程2没有得到GIL锁,意味着CPU2一直是闲置的,无法发挥多核的优势。

四、线程释放GIL

1.在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL。
2.Python 3.x使用计时器Time Tick(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100。

五、多线程利用多核的优势

计算密集型

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

在4核及以上 的情况下:

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

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

IO 密集型

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

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

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

总结

       开发的软件大多是 IO 密集型,所以即使存在 GIL 锁,开启多线程也是有优势的并且,可以同时开启多进程与多线程,同时兼并二者的优点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,GIL(全局解释器)是一种机制,它确保在任何给定时间只有一个线程在解释器中执行字节码。这意味着在多线程的情况下,Python的多线程并不能真正实现并行执行,而只是并发执行。 GIL的存在是为了保护Python解释器内部数据结构的一致性,因为这些数据结构在多线程环境下可能会出现竞争条件。然而,这也导致了Python在处理计算密集型任务时的性能问题,因为只有一个线程可以执行字节码。 虽然GIL对于IO密集型任务并不是一个问题,因为线程在等待IO操作完成时会释放GIL,但对于计算密集型任务,GIL会成为性能瓶颈。 要解决GIL的限制,有几种方法可以尝试: 1. 使用多进程而不是多线程:Python的multiprocessing模块提供了一种在多个进程中执行任务的方式,每个进程都有自己的解释器和GIL。这样可以实现真正的并行执行。你可以使用multiprocessing模块来将计算密集型任务分配给多个进程执行。 2. 使用其他解释器:除了CPython,还有其他的Python解释器,如Jython、IronPython和PyPy。这些解释器没有GIL的限制,因此可以实现真正的并行执行。但需要注意的是,这些解释器可能不支持所有的Python库和功能。 3. 使用C扩展:对于计算密集型任务,可以使用C扩展来绕过GIL。通过将计算部分的代码编写为C扩展,可以在不受GIL限制的情况下执行计算。 下面是一个使用多进程的示例代码,演示了如何绕过GIL实现并行执行: ```python from multiprocessing import Pool def calculate_square(n): return n * n if __name__ == '__main__': numbers = [1, 2, 3, 4, 5] pool = Pool() result = pool.map(calculate_square, numbers) print(result) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值