news 2026/9/7 22:43:18

python GIL全局解释器锁的理解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python GIL全局解释器锁的理解

GIL的全称为Lock, 其意思是全局解释器锁, 这个GIL并非其特性, 它是仅在解释器里得以引入的某个概念, 而于其他语言所编写成的解释器里面就不存在这个GIL, 例如Pypy。

为什么会有gil?:

因为电脑出现多核CPU以及CPU频率得到提升因而为充分利用多核处理器多线程编程方式更加普及, 随之而来的困难是线程间数据一致性和状态同步的问题, 又因利用了多核所以避免不了这个困难存在, 为解决数据无法同步的问题故而设计了gil全局解释器锁。

提及gil解释器锁, 我们常常会想到, 在多线程里来共享全局变量之际, 会存在线程会针对全局变量作出资源竞争, 会致使对全局变量的修改生成并非我们期望的状貌, 而在那个时候我们所运用的是处于线程模块当中的互斥锁, 如此一来每次针对全局变量开展操作之时, 仅有一个线程能够获取到这个全局变量;瞧瞧下面的代码:

importthreading global_num =0deftest1():globalglobal_numforiinrange(1000000): global_num +=1print("test1",global_num)deftest2():globalglobal_numforiinrange(1000000): global_num +=1print("test2",global_num) t1 = threading.Thread(target=test1) t2 = threading.Thread(target=test2) t1.start() t2.start()

在上述的示例里, 我们构建了两个线程, 用以对相关操作进行加一竞赛, 然而最终呈现的结果, 并非是我们所期望达成的那般, 因此我们于此处增添了互斥锁。

importthreadingimporttime global_num =0lock = threading.Lock()deftest1():globalglobal_num lock.acquire()foriinrange(1000000): global_num +=1lock.release()print("test1",global_num)deftest2():globalglobal_num lock.acquire()foriinrange(1000000): global_num +=1lock.release()print("test2",global_num) t1 = threading.Thread(target=test1) t2 = threading.Thread(target=test2) start_time = time.time() t1.start() t2.start()

这一回能够获取到我们所期望的结果, 在先前我的博客文章当中曾经提及过这个问题, 在此处就不再过多啰嗦了。

在解释器当中, 当咱们的代码存在一个线程着手访问解释器之际, GIL会将那个大锁锁住, 这时其他的线程就只能干巴巴地等着, 没办法对解释器的资源展开访问, 这一情况同咱们的互斥锁相仿。而仅限这个历程发生在咱们这儿, 并且也要等这个线程被分配的时间到达后, 该线程把gil释放掉, 跟咱们互斥锁的lock.()情形类似, 另外的线程才开始运转, 严格来讲, 这无疑同样是个单线程。

瞅瞅下面这幅图, 仅仅是把我第一段代码里头的变量换成count, 针对此处我们不理睬互斥锁, 单单去思考gil。

执行过程:1.拿到全局变量count

2.申请到解释器的gil

3.解释器调用系统原生线程

4.在cpu1上执行规定的时间

5.执行的时间已然到了, 有着要求去释放gil , 等到下一次获取到gil的时候, 该程序会从这里接续着本次开启执行。

6.拿到了全局变量, 这时针对全局count的操作尚未完成, 所以所拿到的以及拿到的count实际上是一样的, 像这样也就易于解释为何结果不是200万 而是少于200万。

7.申请到了gil锁

8.调用原生的线程

9.若为单核的中央处理器, 那么便会放置于中央处理器1上去运行, 接着, 并非关键之处在于, 就如同在中央处理器3上进行运行这般。

10.执行规定的时间,此时完成了对count的加一操作

11.此时此刻, 执行时间尚未抵达, 线程2完成了针对count的操作, 随之将count进行了加一的动作, 并且随之释放了gil锁。

12.线程1又申请到了gil锁,重复之前的操作。

13.线程1, 对count执行操作, 数量为万, 完成操作时, 执行时间已到, 此时释放gil锁。

综合上面的步骤就能很好的理解gil锁

哪些情况适合用多线程呢:

只要当前正处于开展耗时的IO操作的时段, 能够将GIL释放掉, 因此只要是处于IO密集型的代码范围之中, 运用多线程便是颇为适宜的。

哪些情况适合用多进程呢:

用于计算密集型,比如计算某一个文件夹的大小。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 22:41:23

支持云盘在线播放的Apple TV软件推荐2026

想在 Apple TV 上直接在线播放阿里云盘、百度网盘里的视频,不是靠单一 App 就能通吃,但用对播放器可以少走弯路。2026 年比较稳的方案有三类:Plex 适合有媒体库需求的用户,nPlayer 适合文件夹直连党,Kodi 配合 Alist/W…

作者头像 李华
网站建设 2026/9/7 22:41:05

MyPy 安装与配置快速教程:新手如何第一次跑通静态类型检查

MyPy 安装与配置快速教程:新手如何第一次跑通静态类型检查 【免费下载链接】mypy Optional static typing for Python 项目地址: https://gitcode.com/GitHub_Trending/my/mypy 写 Python 时最坑的类型 bug,往往要等程序跑起来才暴露。MyPy 在代码…

作者头像 李华
网站建设 2026/9/7 22:40:17

2026深度解读:Work Agent与传统办公系统的能力差异

2026深度解读:Work Agent与传统办公系统的能力差异 办公软件已经深度渗透企业日常业务,文档协作、流程审批、报表统计等工具承担着组织内大部分标准化工作。伴随AI Agent技术落地,一类可以自主完成长链任务的工作助手开始进入办公场景。不少从…

作者头像 李华
网站建设 2026/9/7 22:38:29

芯片赛道开发者切入指南:MCU架构、选型与工具链深度拆解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 22:36:11

万代DX假面骑士黎明驱动器开箱测评:从剧情到收藏的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华