纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Python与GIL互斥锁 Python编程中Python与GIL互斥锁关系作用分析

somenzz   2021-09-14 我要评论
想了解Python编程中Python与GIL互斥锁关系作用分析的相关内容吗somenzz在本文为您仔细讲解Python与GIL互斥锁的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Python编程,Python与GIL互斥锁下面大家一起来学习吧

我们知道在 CPython 中有一个全局解释器锁英文叫 global interpreter lock简称 GIL是一个互斥锁用来保护 Python 世界里的对象防止同一时刻多个线程执行 Python 的字节码从而确保线程安全这导致了 Python 的线程无法利用多核 CPU 的优势因此有人说 Python 的多线程是伪多线程性能不高那么 Python 将来有可能去除 GIL 吗?

要回答这个问题先从 GIL 的起源进行分析

GIL 的起源

Python 第一次发布是在 1991 年当时的 CPU 都是单核单核中多线程主要为了一边做IO一边做 CPU 计算而设计的Python 编译器是由 C 语言编写的因此也叫 CPython那时候很多编程语言没有自动内存管理的功能为了实现自动垃圾回收Python 为每一个对象进行了引用计数当引用计数为 0 的时候说明该对象可以回收从而释放内存了比如:

>>> import sys
>>> data = { 'gzh': 'Python七号'}
>>> var1 = data
>>> sys.getrefcount(data)
3
>>> 

这里 data 对象就有 3 个引用 一个是本身一个是变量 var1一个是 getrefcount 函数的参数如果此时又有一个线程引用了 data那么引用计数再增加 1如果某个线程使用了 data 后运行结束那么引用计数就减少 1多线程对同一个变量「引用计数」进行修改就会遇到 race conditions(竞争)为了避免 race conditions最简单有效的办法就是加一个互斥锁

如果对每一个对象都加锁有可能引发另一个问题就是死锁而且频繁的获取和释放会导致性能下降最简单有效的方法就是加一个解释器锁线程在执行任何字节码时都先获取解释器锁这就避免了死锁而且不会有太多的性能消耗当时 CPU 都是单核而且这种 GIL 设计简单并不会影响性能因此一直沿用至今天GIL 存在最主要的原因就是因为 Python 的内存管理不是线程安全的这就是 GIL 产生并存在的主要缘由

尝试消除 GIL

CPU 进入多核时代后可以同时做多个计算任务, GIL 才真正变成问题在 1999 年有个叫 Greg Stein 的大佬基于 Python 1.5 版本消除了 GIL取代代之的是在可变数据结构上加上更细粒度的锁也提交了补丁用于去除对全局可变对象的依赖然后在标准测试时表明去除 GIL 后单线程比不去除时慢了近 2 倍测试的机器还是当时性能最好 Windows 机器也就是说除去了 GIL 后你使用 2 个 CPU 才能获取比原来 1 个 CPU 稍微好一点的性能这种提升明显得不偿失Greg Stein 的尝试也就失败告终

Python 之父 Guido van Rossum 也欢迎社区的志愿者去尝试去除 GIL只要不降低单线程的性能但他也提到去掉 GIL 不是一件容易的事

Python 开发者邮件列表中也偶尔会有去除 GIL 的议题但是以下需求必须满足:

  • 简单从长远来看该方案必须是可实施、可维护的
  • 并发去除 GIL 必须能提升多线程的性能
  • 速度去除 GIL 不能降低单线程的性能
  • 满足 CPython 的特性该方案必须支持 CPython 的功能比如 __del__ 和弱引用
  • API 的兼容性该方案应与所有现有CPython扩展使用的宏在源方面兼容
  • 及时销毁不可达对象回收内存
  • 有序销毁比如不可达对象 X 引用了 A那么应该在销毁 A 之前先销毁 X(有些垃圾回收算法并不能做到这一点)

有些需求不容易被满足比如 457目前还没有人满足以上需求的同时去除 GIL 成功的

积重难返

这些年 Python 实在太火了很多优秀的库都是基于 CPython 进行编写的很多都是 90 年代的 C 扩展库如果要除去 GIL那么很多基于 GIL 编写的 C 扩展便无法使用也就是去了 GILPython 生态有很多扩展或三方库者无法使用

还有一个很明显的例子Python 解释器不止有 CPython还有用 Java 编写的 Python.NET 实现的 IronPython这些解释器完全没有 GIL可是有多少人为它们编写扩展呢?

Python 之所以如此火爆与它有着丰富的三方库开箱即用有着很大的关系积重难返去除 GIL 很困难

为什么 Python3 一开始时不去除 GIL

Python3 在最开始时是有机会实现很多新功能在此过程中打破了一些现有的 C 扩展然后需要更新和移植更改以配合 Python 3这也是 Python3 一开始不被社区所接受的原因

与 Python2 相比删除 GIL 将使 Python3 在单线程性能方面更慢而且很多优秀的扩展将不能再使用如果真的这样可以想象 Python3 不可能有未来最终的结果是 Python3 仍然保持有 GIL

但 Python3 也为现有的 GIL 带来了重大改进在 Python 3.2 版本中确保了计算密集型线程和 I/O 密集型线程并存时 I/O 密集型长期获取不到 GIL 而无法执行的问题提升了多线程的性能

最后的话

Python 因为内存管理不是线程安全的因此自出生起就自带 GIL然后很多扩展都是在 GIL 的保护下编写的时间一长积重难反Python3 一开始也因去除 GIL 导致单线程性能下降的问题而保留 GIL现在已经是 Python3.9 版本了将来 Python 去除 GIL 的可能性微乎其微换句话说去除 GIL 的 Python 也就不是我们认识的 Python 了

不过不必沮丧GIL 影响的也仅仅是多线程执行计算密集型的任务罢了这种场景大多数程序员都很少遇到即使有可以使用多进程来避免 GIL 的影响或者使用其他编程语言实现任何编程语言或技术都不是十全十美的发挥所长是最重要的即使有 GIL我也不在乎也会依然使用 Python


相关文章

猜您喜欢

  • C 语言常量 C 语言基础之初识 C 语言常量

    想了解C 语言基础之初识 C 语言常量的相关内容吗吞吞吐吐大魔王」在本文为您仔细讲解 C 语言常量的相关知识和一些Code实例欢迎阅读和指正我们先划重点:C,语言常量下面大家一起来学习吧..
  • docker部署code-server docker部署code-server的方法

    想了解docker部署code-server的方法的相关内容吗barwe在本文为您仔细讲解docker部署code-server的相关知识和一些Code实例欢迎阅读和指正我们先划重点:docker部署code-server,docker,code-server下面大家一起来学习吧..

网友评论

Copyright 2020 www.sopisoft.net 【绿软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式