前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文理解Python的全局解释器锁(GIL)

一文理解Python的全局解释器锁(GIL)

原创
作者头像
Lorin 洛林
发布2024-04-30 13:45:36
7900
代码可运行
发布2024-04-30 13:45:36
举报
文章被收录于专栏:Python 技术小屋Python 技术小屋
运行总次数:0
代码可运行

前言

  • 在Python中,全局解释器锁(Global Interpreter Lock,简称GIL)是一个重要的概念,它对Python解释器的并发执行模型产生了重大影响。本文将介绍GIL的概念、原理以及对Python多线程程序执行效率的影响,并附带详细的代码案例进行说明。

什么是 GIL

  • GIL是Python解释器中的一个互斥锁,它确保在同一时刻只有一个线程能够执行Python字节码。这意味着在多线程环境下,Python解释器无法同时利用多个CPU核心进行并行执行,因为只有一个线程能够执行Python字节码指令。

GIL 的工作原理

  • 当Python解释器运行Python代码时,它会获取GIL,然后执行相应的字节码指令。其他线程想要执行Python字节码时,必须先获取GIL,但只有在当前线程释放GIL后才能获得。因此,只有一个线程能够在任意时刻执行Python字节码,这就是GIL的工作原理。

GIL 的影响

多线程

  • 尽管Python完全支持多线程编程, 但是解释器的C语言实现部分在完全并行执行时并不是线程安全的。 实际上,解释器被一个全局解释器锁保护着,它确保任何时候都只有一个Python线程执行。 GIL最大的问题就是Python的多线程程序并不能利用多核CPU的优势 (比如一个使用了多个线程的计算密集型程序只会在一个单CPU上面运行)。
  • 有一点要强调的是GIL只会影响到那些严重依赖CPU的程序(比如计算型的)。 如果你的程序大部分只会涉及到I/O,比如网络交互,那么使用多线程就很合适, 因为它们大部分时间都在等待。
  • 对于依赖CPU的程序,你需要弄清楚执行的计算的特点。 例如,优化底层算法可能要比使用多线程运行快得多。 类似的,由于Python是解释执行的,如果你将那些性能瓶颈代码移到一个C语言扩展模块中, 速度也会提升的很快。如果你要操作数组,那么使用NumPy这样的扩展会非常的高效。 最后,你还可以考虑下其他可选实现方案,比如PyPy,它通过一个JIT编译器来优化执行效率。

多进程

  • 在 Python 中,GIL(全局解释器锁)只影响到了多线程,而不会对多进程产生直接的影响。多进程是通过创建不同的 Python 解释器来实现的,因此每个进程都有自己的独立 GIL,它们之间互不影响。

如何解决 GIL 的缺点

示例代码

  • 代码版本 Python 3.x
  • 如我们如何优化下列代码:
代码语言:python
代码运行次数:0
复制
# Performs a large calculation (CPU bound)
def some_work(args):
    ...
    return result

# A thread that calls the above function
def some_thread():
    while True:
        ...
        r = some_work(args)
    ...

使用多进程的方式

  • 如果你完全工作于Python环境中,你可以使用 multiprocessing 模块来创建一个进程池, 并像协同处理器一样的使用它,每个进程有独立的 GIL。
代码语言:python
代码运行次数:0
复制
# Processing pool (see below for initiazation)
pool = None

# Performs a large calculation (CPU bound)
def some_work(args):
    ...
    return result

# A thread that calls the above function
def some_thread():
    while True:
        ...
        r = pool.apply(some_work, (args))
        ...

# Initiaze the pool
if __name__ == '__main__':
    import multiprocessing
    pool = multiprocessing.Pool()

使用C扩展编程技术

  • 主要思想是将计算密集型任务转移给C,跟Python独立,在工作的时候在C代码中释放GIL。 可以通过在C代码中插入下面这样的特殊宏来完成:
代码语言:c
复制
#include "Python.h"
...

PyObject *pyfunc(PyObject *self, PyObject *args) {
   ...
   Py_BEGIN_ALLOW_THREADS
   // Threaded C code
   ...
   Py_END_ALLOW_THREADS
   ...
}
  • 如果使用其他工具访问C语言,比如对于Cython的ctypes库,你不需要做任何事。 例如,ctypes在调用C时会自动释放GIL。

参考

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 什么是 GIL
  • GIL 的工作原理
  • GIL 的影响
    • 多线程
      • 多进程
      • 如何解决 GIL 的缺点
        • 示例代码
          • 使用多进程的方式
            • 使用C扩展编程技术
            • 参考
            • 个人简介
            相关产品与服务
            云数据库 MySQL
            腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档