热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

并发编程之GIL锁

并发编程之GIL锁1.定义​GIL(Global_Interpreter_Lock)全局解释器锁:​在cpython中,GIL是一个互斥锁,为了防止多个本地线程在同一时间执行pytho

并发编程之GIL锁

1.定义

​ GIL(Global_Interpreter_Lock)全局解释器锁:

​ 在cpython中,GIL是一个互斥锁,为了防止多个本地线程在同一时间执行python字节码,因为cpython中的内存管理是非线程安全的,而cpython中的很多特性都依赖于这个特性.

2.cpython解释器与python程序之间的关系

  1. python程序本质就是一堆字符串,所以运行一个python程序时 必须要开启开启一个解释器

  2. 但是在一个python程序中解释器只有一个 所有代码都要交给它来解释执行

  3. 当有多个线程都要执行代码时就会产生线程安全问题

3.cpython解释器与GC(垃圾回收线程)的问题

python会自动帮我们处理垃圾 清扫垃圾也是一对代码 也需要开启一个线程来执行

也就是说就算程序没有自己开启线程 内部也有多个线程

GC线程与我们程序中的线程就会产生安全问题

例如: 线程1 要定义一个变量a=10

步骤:1.申请内存空间,

​ 2.数据存入空间(变量值的引用计数为0)

​ 若此时,CPU切换到GC进程,将会出发垃圾回收机制

​ 3.引用计数+1

4.带来的问题

​ GIL是一把互斥锁,降低效率:具体表现是 在CPython 即便开启了多线程 而且CPU也是多核的 却无法并行执行任务;因为解释器只有一个 同一时间只能有一个任务在执行 .

5.如何解决

无彻底办法解决,只能尽可能的避免GIL锁影响我们的效率

1.使用多进程能够实现并行,从而更好的利用多核CPU

2.对任务进行区分

​ 任务可以分为两类

​ 1.计算密集型 基本没有IO 大部分时间都在计算 例如人脸识别 图像处理

​ 由于多线程不能并行 应该使用多进程 将任务分给不同CPU核心

​ 2.IO密集型 计算任务非常少,大部分时间都在等待IO操作

​ 由于网络IO速度对比CPU处理速度非常慢, 多线程并不会造成太大的影响

​ 另外如有大量客户端连接服务 进程根本开不起来 只能用多线程

6.关于性能的讨论

​ 之所以加锁是为了解决线程安全问题

​ 由于有了锁 导致Cpython中多线程不能并行只能并发

​ 但是我们不能因此否认python

​ 1.python是一门语言 ,GIL是Cpython解释器的问题

​ 2.如果是单核CPU ,GIL不会造成任何影响

​ 3. 由于目前大多数程序都是基于网络的,网络速度对比CPU是非常慢的, 导致即使多核CPU也无法提高效率

​ 4. 对于IO密集型任务 不会有太大的影响

​ 5.如果没有这把锁 我们程序猿将必须自己来解决安全问题

#性能测试
#计算密集型(多进程强于多线程)
from multiprocessing import Process
from threading import Thread
import time

def task():
    for i in range(100000000):
        1+1

if __name__ == '__main__':
    start = time.time()

    ps = []
    for i in range(5):
        # p = Process(target=task)    #耗时:9.214441299438477
        # p =Thread(target=task)       #耗时:16.144373178482056
        p.start()
        ps.append(p)

    for i in ps:i.join()

    #计时
    print(time.time()-start)
    
    
# IO密集型任务(频繁的用户交互和打开文件等费时操作)
def task():
    for i in range(100):
        with open(r"1.死锁现象.py",encoding="utf-8") as f:
            f.read()

if __name__ == '__main__':
    start_time = time.time()

    ps = []
    for i in range(10):
        p = Process(target=task)
        # p = Thread(target=task)
        p.start()
        ps.append(p)

    for i in ps:i.join()
    print("共耗时:",time.time()-start_time)

# 多线程胜于多进程    
 

7.GIL于自定义锁的区别

GIL锁住的是解释器级别的数据

自定义锁,锁的是解释器以外的共享资源 例如:硬盘上的文件 控制台

对于这种不属于解释器的数据资源就应该自己加锁处理


推荐阅读
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 笔记day2 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
author-avatar
moTzxx
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有