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

yizhihongxing

浅谈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中的time模块)来模拟时间的流逝,并不断更新时钟的显示。因此,要实现一个模拟时钟,需要掌握以下几个关键点: 计算机系统计时功能的使用方法 时钟的外观和显示形式设计 …

    python 2023年6月2日
    00
  • 如何使用 Redis 存储和检索数据?

    如何使用 Redis 存储和检索数据? Redis 是一个开源的内存数据结构存储系统,它支持多种数据结构,如字符串、哈希、列表、集合等。Redis 常用于缓存、消息队列实时数据处理等场景。在本文中,我们将介绍如何使用 Redis 存储和检索数据的整使用攻略,包括连接 Redis 数据库、设置和获取键值对、使用哈希、列表和集合等数据结构、发布和订阅消息操作。 …

    python 2023年5月12日
    00
  • python 密码学示例——理解哈希(Hash)算法

    以下是关于“Python密码学示例——理解哈希(Hash)算法”的完整攻略: 简介 哈希(Hash)算法是一种常用的密码学算法,它可以将任意长度的数据转换为固定长度的数据,通常用于数据的完整性验证和数字签名等场景。在本教程中,我们将介绍如何使用Python实现哈希算法,并提供两个示例。 算法1:MD5哈希算法 MD5哈希算法是一种常用的哈希算法,它可以将任意…

    python 2023年5月14日
    00
  • Python版Mssql爆破小脚本

    Python版Mssql爆破小脚本是一款用Python语言编写的用于MSSQL爆破的工具。使用该脚本可以快速有效地针对MSSQL进行爆破,获取登录账户的正确密码。 以下是Python版Mssql爆破小脚本的完整攻略: 1. 配置环境 在使用Python版Mssql爆破小脚本之前,需要先进行环境配置。具体操作如下: 安装Python环境 Python版Mssq…

    python 2023年5月20日
    00
  • Python groupby()和reduce()

    Python中的groupby()和reduce()都是用于对可迭代对象进行操作的函数。其中,groupby()通常用于按照某个条件对可迭代对象进行分组,将分组后的结果返回为一个迭代器;而reduce()则是用于对可迭代对象的所有元素进行合并操作,返回一个单一的值。下面分别进行详细介绍。 groupby()函数 基本使用方法 groupby()函数的基本使用…

    python-answer 2023年3月25日
    00
  • Python如何读取文件中图片格式

    Python提供了多种读取文件中图片的方式,常用的有使用Pillow库、使用OpenCV库等。本篇攻略将详细讲解这两种主要方法的使用。 使用Pillow库读取文件中图片格式 Pillow是Python图像处理库,可以用来打开、保存、创建各种格式的图片文件,具有广泛的应用场景。 下面是一个读取图片的示例代码: from PIL import Image # 打…

    python 2023年5月18日
    00
  • linux 下python多线程递归复制文件夹及文件夹中的文件

    下面是关于在Linux下使用Python多线程递归复制文件夹及文件夹中的文件的攻略。具体步骤如下: 1. 导入必要的库 在 Python 里进行文件操作一般使用 os 和 shutil 这两个库。同时,由于涉及多线程操作,我们还需要使用 threading 和 queue 两个库。首先导入它们: import os import shutil import …

    python 2023年5月19日
    00
  • Python工具箱系列(三十)

    PostgreSQL MySQL的口号是“世界上最流行的开源关系型数据库”,而PostgreSQL的Slogan则是“世界上最先进的开源关系型数据库(PostgreSQL: The World’s Most Advanced Open Source Relational Database)”,一看这就是一对老冤家了。这两个口号很好的反映出了两者的形象特质:P…

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