浅谈Python中的全局锁(GIL)问题

浅谈Python中的全局锁(GIL)问题

什么是GIL

GIL 全称 Global Interpreter Lock,意为全局解释器锁。在 Python 中,一次只能执行一个线程,所以为了保证线程安全,引入了 GIL 的概念。GIL 是 Python 解释器中自带的机制,用来保证同一时刻只有一个线程在执行 Python 代码。当一个线程开始执行 Python 代码时,GIL 就会获得并锁住 Python 解释器,保证只有这个线程可以接触到解释器。

GIL的问题

GIL 的存在使得 Python 的多线程执行遭遇瓶颈。虽然 Python 可以使用多进程的方式解决多线程所面临的瓶颈,但多进程的开销相比于多线程会比较大。而且在某些场景下,使用多线程更为方便。

举个例子

例子1

import threading

num = 0

def thread_test():
    global num
    for i in range(1000000):
        num += 1
    print(num)

thread1 = threading.Thread(target=thread_test)
thread2 = threading.Thread(target=thread_test)
thread1.start()
thread2.start()

以上代码会创建两个线程,每个线程都会对 num 进行 1000000 次加 1 操作,并打印最终的计数结果。

但是执行的结果可能出乎想象:

1265211
1394415

实际上,我们想要的结果应该是 2000000。原因就在于 GIL。

在使用多线程执行 Python 代码时,由于 GIL 的存在,每一个时刻只有一个线程在执行 Python 代码。在本例中,两个线程交替获得 GIL,一次只能做一次加法。最终的结果可能超出预期。

例子2

import threading

num = 0

def thread_test():
    global num
    for i in range(1000000):
        num += 1
    print(num)

thread1 = threading.Thread(target=thread_test)
thread2 = threading.Thread(target=thread_test)
thread3 = threading.Thread(target=thread_test)
thread1.start()
thread2.start()
thread3.start()

以上代码会创建三个线程,每个线程都会对 num 进行 1000000 次加 1 操作,并打印最终的计数结果。

执行的结果可能如下:

2324507
2424009
3553736

同样也是超出预期的。

在这个例子中,如果想要结果正确,可以使用 threading.Lock() 对共享变量进行锁定:

import threading

num = 0
lock = threading.Lock()

def thread_test():
    global num
    for i in range(1000000):
        lock.acquire()
        num += 1
        lock.release()
    print(num)

thread1 = threading.Thread(target=thread_test)
thread2 = threading.Thread(target=thread_test)
thread3 = threading.Thread(target=thread_test)
thread1.start()
thread2.start()
thread3.start()

使用 lock 后,每个线程在执行对 num 的加 1 操作前都会尝试获取锁,如果拿到锁后才执行加法操作。这样可以保证在同一时刻只有一个线程对 num 进行操作,最终达到正确的结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Python中的全局锁(GIL)问题 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • python数据可视化的那些操作你了解吗

    当涉及到数据可视化时,Python提供了许多强大的工具和库。以下是Python数据可视化的攻略: 一、选择Python的可视化库 Python的数据可视化库有很多,如matplotlib,seaborn,plotly等等。选择库的关键在于根据项目的需要来选择最适合的库。例如,用于数据探索或图形化呈现的图表类型,不同的库可能采用不同的格式或搭配方式。下面是几个…

    python 2023年5月19日
    00
  • Python实现队列的方法示例小结【数组,链表】

    Python实现队列的方法示例小结 什么是队列 队列是一种数据结构,它基于先进先出 (FIFO) 的原则,数据元素的插入是在队列的末尾进行,数据元素的删除是在队列的头部进行。 队列的应用场景 队列的应用场景非常广泛,例如: 操作系统中的任务调度; 网络传输中的数据包传输; 生产者消费者问题; 页面请求缓存等。 Python实现队列的方法 数组实现队列 数组实…

    python 2023年6月3日
    00
  • Python实现合并同一个文件夹下所有PDF文件的方法示例

    Python实现合并同一个文件夹下所有PDF文件的方法示例 如果你想要将一个文件夹下的所有PDF文件合并成一个文件,那么Python可以为你提供一个非常便利的方法。下面将介绍如何使用Python来实现合并同一个文件夹下的所有PDF文件。 安装pyPDF2 首先,我们需要安装一个Python第三方库——pyPDF2,它是一个操作PDF文件的工具包。我们可以通过…

    python 2023年6月5日
    00
  • python 实现dcmtk关联pacs功能推送下拉影像(推荐)

    Python实现DCMTK关联PACS功能推送下拉影像 介绍 DCMTK是医学图像处理工具,可以实现医学影像文件的读取、修改、存储、传输等功能。在医疗行业,常常需要将医学影像文件从一台设备传输到另一台设备,例如从医学影像设备传输到医院的PACS系统。本文将介绍如何使用Python和DCMTK实现关联PACS功能,将医学影像文件推送到PACS系统。 步骤 1.…

    python 2023年6月13日
    00
  • 老生常谈Python之装饰器、迭代器和生成器

    老生常谈Python之装饰器 装饰器(Decorator)是 Python 的一种高级语法,可以动态地修改类或函数的行为,在不改变原有代码的前提下增加新的功能或特性。 装饰器使用 @ 符号一般放在函数定义的上一行,并紧跟着装饰器函数名称。示例如下: def decorator(func): def wrapper(): print("Do some…

    python 2023年6月2日
    00
  • python自动化测试之DDT数据驱动的实现代码

    下面是“python自动化测试之DDT数据驱动的实现代码”的完整攻略: 一、什么是DDT数据驱动? DDT,即 Data-Driven Testing,数据驱动测试。它是一种基于数据的测试方法,它的主要思想是不同的输入数据可以得到不同的测试结果,因此我们可以通过不同的数据来验证系统的稳定性和可靠性。DDT可以通过将测试数据与测试脚本分离,实现更好的复用性和可…

    python 2023年5月19日
    00
  • Python Request爬取seo.chinaz.com百度权重网站的查询结果过程解析

    下面我将详细讲解”PythonRequest爬取seo.chinaz.com百度权重网站的查询结果过程解析”的完整实例教程。 准备工作 安装Python环境 安装Python第三方库requests和beautifulsoup4 获取查询结果 首先,我们需要获取要查询的网站的百度权重,可以使用Python Requests库进行查询。 import requ…

    python 2023年5月13日
    00
  • python实现超市进销存管理系统

    Python实现超市进销存管理系统攻略 1. 系统设计 超市进销存管理系统主要包含以下几个模块: 商品管理 进货管理 销售管理 库存管理 报表统计 其中,商品管理模块主要负责商品的添加、修改、删除和查询;进货管理模块主要负责进货单的添加、查询以及进货单与商品库存的更新;销售管理模块主要负责销售单的添加、查询以及销售单与商品库存的更新;库存管理模块主要负责商品…

    python 2023年5月30日
    00
合作推广
合作推广
分享本页
返回顶部