GIL 锁或将在 CPython 中成为可选项
哈喽大家好,我是咸鱼
几天前有媒体报道称,经过多次辩论,Python 指导委员会打算批准通过 PEP 703 提案,让 GIL(全局解释器)锁在 CPython 中成为一个可选项
PEP 703 提案主要目标是使 GIL 变成可选项,即允许 Python 解释器在特定情况下不使用GIL
这将允许 Python 在多核处理器上更好地利用并行性,从而提高多线程程序的性能
PEP 703 提案建议新增一个配置项 --disable-gil
,加了这个选项之后就可以关闭 GIL 锁,如果想要开启 GIL 锁,把 --disable-gil
去掉即可
关于 PEP 703 提案的具体内容有兴趣的小伙伴们可以去看一下
PEP 703 提案:https://peps.python.org/pep-0703/
接下来我们来看下外媒的这篇报道吧!
原文:https://www.infoworld.com/article/3704248/python-moves-to-remove-the-gil-and-boost-concurrency.html
译文如下:
经过多次辩论,Python 指导委员会打算批准 PEP 703 提案——”使全局解释器锁在 CPython 中可选“
PEP 703 提案是多年来尝试移除 Python GIL 锁的最终结果。GIL 锁的移除消除了多线程的主要障碍,使得 Python 成为真正的多核语言,并且显著提高其并行工作负载的性能
有了 PEP 703 提案,Python 中对多线程和并发的一流支持离成为现实又近了一步
为什么要移除 GIL ?
在 python 中,其内存管理系统通过维护每个对象的引用数量来跟踪对象的使用情况(Python 的引用计数机制)
当对象的引用计数减少为 0 时,系统就会删除该对象
由于 Python 诞生于多处理器系统很少见且多核处理器还未出现的时代,所以这种引用计数机制不是线程安全的
相反,Python 通过一次只允许一个线程访问对象来实现线程安全,这便是 GIL 的目的
这些年来许多项目都尝试移除 GIL,它们确实能够使多线程程序运行地更快,但代价是降低了单线程程序的性能
鉴于绝大多数 Python 应用程序都是单线程,所以这是一个糟糕的权衡。尽管对 GIL 的改进提升了 Pyhton 对多线程应用程序的处理,但仍旧是一个严重的瓶颈
Python 的核心开发人员最终决定从 CPython 中移除 GIL,但前提是它可以在不减慢单线程程序速度的情况下完成
没了 GIL,Python 该如何运行?
当前关于 Python 的无 GIL 版本的提案都提到了使用多种技术来使引用计数线程安全,并且维持单线程程序的速度不变或者仅对其产生最小的影响
下面是一些关于无 GIL 版本的提案:
- Biased reference counting(带偏见的引用计数)
单个线程访问的对象的引用计数与多个线程访问的对象的引用计数处理方式不同(单线程的更快一点)
由于大多数对象只被一个线程访问,因此对单线程程序的影响被降到最低
- Immortalization(永生)
某些对象(如 None
)永远不会被回收,因此不需要跟踪它们的引用计数
- Thread-safe memory allocation(线程安全的内存分配)
一个新的 CPython 对象内存分配系统将使垃圾收集器中的对象跟踪更容易,并以线程安全的方式分配内存
- Deferred reference counting(延迟引用计数)
某些对象(如模块中的顶级函数)的引用计数可以安全地延迟。这样可以节省时间和资源
- A revised garbage collector(修改后的垃圾收集器)
CPyhton 垃圾收集器清楚循环对象的引用(比如两个或多个对象互相引用)
无 GIL构建对垃圾收集器做了许多更改,例如删除用于跟踪对象的“生成”系统
如何逐步引入无 GIL 的 Python?
实施 PEP 703 是一个长期项目,将会在几年内分成多个阶段进行。在此期间,CPython 解释器先过渡到使 no-GIL 版本可选,然后是支持,最后成为标准
为了实现这个目标,CPython 的开发者将会为 CPython 添加一个实验性的 ’no-GIL‘ 构建模式,以便大家可以在有或没有 GIL 的情况下编译 CPython 的版本
最终,no-GIL 构建将成为默认值
下面则是相关的计划:
1、no-GIL 是可选项
对于 CPython 开发人员和 Python 社区来说,no-GIL CPython 的第一个版本将是实验性
这个实验阶段有几个目标:
- 首先让 Python 社区的其他成员参与进来。对 Python 的任何重大更改都需要更广泛的Python 社区的支持。实验性版本为 Python 用户提供了一种安全地试验测试其代码的方法,并且能够观察非线程和线程代码的行为方式
- 其次让 Python 发行版可以选择(而不是”要求“)提供 no-GIL 的 Python。像 Conda 或WinPython 这样的 Python 发行版需要保证与原有的 CPython 兼容。在过渡阶段,安装的时候可以提供常规或者 no-GIL 版本的 CPython 选项,这将允许 Conda 或WinPython 用户选择最适合他们需求的版本
- 最后确定 no-GIL 项目是否值得。如果社区大规模尝试 no-GIL 的构建后对结果不满意,CPython 核心开发人员保留退出的权利。双重构建意味着在短期内会增加维护负担,但如果 no-GIL 项目被证明不值得,他们也有退路
2、支持 no-GIL Python
下一阶段将提供 no-GIL 构建作为 CPython 支持的替代构建
用户可以选择安装 no-GIL 或 GIL 版本,其中任何一个版本都是正式支持的 CPython 版本,可以接收错误修复、安全补丁和更新
这个阶段的一大目标是设置一个期限,使 no-GIL 成为默认值
这可能与其他 Python 功能的弃用和删除在同一时间线上发生——至少两三个版本,也意味着至少两到三年
3、no-GIL 成为默认
最后阶段是将 CPython 的 no-GIL 版本作为默认版本,并从 CPython 中删除所有与 GIL 相关的代码
”我们不想等待太久“,CPython 核心开发人员 Thomas Wouters 写道,“因为拥有两种通用的构建模式可能会给社区带来沉重的负担(例如,它可以将测试资源和调试场景加倍),但我们也不能急于求成。我们认为可能需要长达五年的时间才能达到这个阶段
移除 GIL 的最大挑战
尽管技术挑战令人生畏,但这项计划的最大挑战不仅仅是技术挑战。更大的问题是如何使 Python 生态系统的其余部分与这些变化保持一致且确保 no-GIL 的 Python 不会产生比它解决的问题更多的问题
根据 Wouters 的说法,”...适应非 GIL 构建所需的第三方代码的任何更改都应该只适用于 GIL 构建(尽管仍然需要解决与旧 Python 版本的向后兼容性问题)“
如上所述,另一个重大挑战是”带领Python社区的其他成员,” Wouters 说,“……确保我们想要做出的改变,以及我们希望他们做出的改变,是可以接受的
“在我们承诺完全切换到 no-GIL 构建之前,我们需要看到社区对它的支持,” Wouters说。“我们不能只是改变默认值,然后期望社区找出他们需要做些什么来支持它”
Python 社区在从 Python 2 过渡到 Python 3 的过程中经历了巨大的成长痛苦,因此任何像移除 GIL 这样的重大更改都必须完全向后兼容
正如 Wouters 所说,“我们不希望再出现 Python 3 的情况。”
不过在危险和挑战之外,还有一个巨大的回报——Python 最终支持了程序员在 21 世纪所期望的并行性
GIL 锁或将在 CPython 中成为可选项的更多相关文章
- CPython中的GIL
GIL:全局解释器锁(cpython中) GIL产生的背景,由于C语言底层原因,CPpython中多线程运行,每个线程都需要申请全局资源,但是Cpython并不能应对所有线程同时的资源请求,为防止发生 ...
- Python进阶----GIL锁,验证Cpython效率(单核,多核(计算密集型,IO密集型)),线程池,进程池
day35 一丶GIL锁 什么是GIL锁: 存在Cpython解释器,全名:全局解释器锁.(解释器级别的锁) GIL是一把互斥锁,将并发运行变成串行. 在同一个进程下开启的多个线 ...
- GIL锁、进程池与线程池
1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multip ...
- 并发编程-多线程,GIL锁
本章内容: 1.什么是GIL 2.GIL带来的问题 3.为什么需要GIL 4.关于GIL的性能讨论 5.自定义的线程互斥锁与GIL的区别 6.线程池与进程池 7.同步异步,阻塞非阻塞 一.什么是GIL ...
- Python中的GIL锁
在Python中,可以通过多进程.多线程和多协程来实现多任务. 在多线程的实现过程中,为了避免出现资源竞争问题,可以使用互斥锁来使线程同步(按顺序)执行. 但是,其实Python的CPython(C语 ...
- 操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁
并发编程前言: 1.网络应用 1)爬虫 直接应用并发编程: 2)网络框架 django flask tornado 源码-并发编程 3)socketserver 源码-并发编程 2.运维领域 1)自动 ...
- python 线程(创建2种方式,锁,死锁,递归锁,GIL锁,守护进程)
###############总结############ 线程创建的2种方式(重点) 进程:资源分配单位 线程:cpu执行单位(实体) 线程的创建和销毁的开销特别小 线程之间资源共享,是同一个 ...
- GIL锁
GIL锁 在CPython中,这个全局解释器锁,也称 ...
- Python GIL锁
GIL全局解释器锁:为了解决多线程修改同一块数据. python的线程是调用操作系统的源生线程,启动时就是调用C语言的C源生接口,python调用C语言接口的线程去执行任务时,必须上下文对应关系传给C ...
- day34 GIL锁 线程队列 线程池
一.Gil锁(Global Interpreter Lock) python全局解释器锁,有了这个锁的存在,python解释器在同一时间内只能让一个进程中的一个线程去执行,这样python的多线程就无 ...
随机推荐
- mongodb c driver bson的嵌套访问与层次结构
使用c访问mongodb,需要用到mongodb c driver.c++的driver也是基于c driver封装的. 在使用c driver访问mongodb时,需要与bson打交道,不过c dr ...
- 嵌入式linux主机通过分区镜像生成固件,DD备份分区后打包成固件,px30刷机教程 ,rockchip刷机教程
我这边有一个工控路由器因为刷机变砖了,网上下载不到固件,自己暂时还没有搞过编译.我找到了同型号的路由器,把它的系统制作成镜像. 具体操作分为三步: 第一步,直接用DD命令备份了几个分区,分区我暂时还不 ...
- Vue项目的创建、运行与端口号修改
前言:Vue-cli是Vue官方提供的一个脚手架,用于快速生成一个Vue的项目模板,依赖于NodeJS环境 NodeJS下载:NodeJS安装下载 Vue-cli下载:Vue-cli下载 一.Vue图 ...
- .NET企业应用安全开发动向-概览
太长不读版:试图从安全的全局视角触发,探讨安全的重要性,讨论如何识别安全问题的方法,介绍.NET提供的与安全相关的基础设施,以及一些与时俱进的安全问题,为读者建立体系化的安全思考框架. 引言 关于&q ...
- [P7880][Ynoi2006] rldcot
[Ynoi2006] rldcot 题目描述 给定一棵 \(n\) 个节点的树,树根为 \(1\),每个点有一个编号,每条边有一个边权. 定义 \(dep(x)\) 表示一个点到根简单路径上边权的和, ...
- Tensorflow2.0使用Resnet18进行数据训练
在今年的3月7号,谷歌在 Tensorflow Developer Summit 2019 大会上发布 TensorFlow 2.0 Alpha 版,随后又发布了Beta版本. Resnet18结构 ...
- Java中获取Class对象的三种方式
在Java中,我们经常需要获取某个类的Class对象,以便进行反射操作.动态加载类或者获取类的信息.本文将介绍Java中获取Class对象的三种常见方式. 1. 使用.class语法 获取Class对 ...
- iMessage群发,iMessage群发基础知识,iMessage群发源代码分享
在当今的数字化时代,即时通讯已经成为我们日常生活和工作中不可或缺的一部分,其中,苹果的iMessage服务因其出色的用户体验和无缝的设备间同步而备受用户喜爱. 然而,你是否想过如何利用iMessage ...
- ElasticSearch之cat indices API
命令样例如下: curl -X GET "https://localhost:9200/_cat/indices?v=true&pretty" --cacert $ES_H ...
- 如何使用Redisson实现分布式锁?
在分布式系统中,当多个线程(或进程)同时操作同一个资源时,为了保证数据一致性问题,所以就需要一种机制来确保在同一时间只有一个线程(或进程)能够对资源进行修改,这就是分布式锁的作用. 分布式锁是一种在分 ...