zoukankan      html  css  js  c++  java
  • 多线程--GIL锁

    GIL

    即全局解释器锁,是一个互斥锁,防止多个线程在同一时间执行python代码,因为在一个python进程中,不仅有主线程而且还有该主线程开启的子线程,还有解释器开启的垃圾回收机等解释器级别的线程。因为所有的代码都是共享的,所以垃圾回收线程也可能同时访问到解释器的代码去执行,所以解决这一问题的方法就是GIL,以保证python解释器同一时间只能执行同一个任务的代码。

    GIL带来的问题

    执行一个py文件,分为三个步骤:

    1. 从硬盘加载python解释器到内存
    2. 从硬盘加载py文件到内存
    3. 解释器解析py文件内容,交给CPU执行

    需要明确的是每当执行一个py文件,就会立即启动一个python解释器

    GIL是CPython解释器独有的,它将线程的并行变为串行,导致效率降低。

    GIL对于性能的影响

    1. 单核下无论IO密集型还是计算密集型GIL都不会产生任何影响
    2. 多核下对于IO密集型任务,GIL会有细微影响,基本可以忽略
    3. CPython中IO密集型任务应该采用多线程,计算密集型应该采用多进程

    另外:之所以广泛采用CPython解释器,就是因为大量的应用程序都是IO密集型的,还有另一个很重要的原因是CPython可以无缝对接各种C语言实现的库,这对于一些数学计算相关的应用程序而言非常的happy,直接就能使用各种现成的算法

    自定义的线程锁和GIL的区别

    GIL保护的是解释器级别的数据安全,比如对象的引用计数,垃圾回收机制等

    对于程序中自己定义的数据则没有任何保护效果

    from threading import Thread,Lock
    import time
    
    a = 0
    def task():
        global a
        temp = a
        time.sleep(0.01) 
        a = temp + 1
    
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(a)
    #1
    

    过程分析:

    1.线程1获得CPU执行权,并获取GIL锁执行代码 ,得到a的值为0后进入睡眠,释放CPU并释放GIL

    2.线程2获得CPU执行权,并获取GIL锁执行代码 ,得到a的值为0后进入睡眠,释放CPU并释放GIL

    3.线程1睡醒后获得CPU执行权,并获取GIL执行代码 ,将temp的值0+1后赋给a,执行完毕释放CPU并释放GIL

    4.线程2睡醒后获得CPU执行权,并获取GIL执行代码 ,将temp的值0+1后赋给a,执行完毕释放CPU并释放GIL,最后a的值也就是1

    之所以出现问题是因为两个线程在并发的执行同一段代码,解决方案就是加锁!

    from threading import Thread,Lock
    import time
    
    lock = Lock()
    a = 0
    def task():
        global a
        lock.acquire()
        temp = a
        time.sleep(0.01)
        a = temp + 1
        lock.release()
    
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(a)
    #2
    

    过程分析:

    1.线程1获得CPU执行权,并获取GIL锁执行代码 ,得到a的值为0后进入睡眠,释放CPU并释放GIL,不释放lock

    2.线程2获得CPU执行权,并获取GIL锁,尝试获取lock失败,无法执行,释放CPU并释放GIL

    3.线程1睡醒后获得CPU执行权,并获取GIL继续执行代码 ,将temp的值0+1后赋给a,执行完毕释放CPU释放GIL,释放lock,此时a的值为1

    4.线程2获得CPU执行权,获取GIL锁,尝试获取lock成功,执行代码,得到a的值为1后进入睡眠,释放CPU并释放GIL,不释放lock

    5.线程2睡醒后获得CPU执行权,获取GIL继续执行代码 ,将temp的值1+1后赋给a,执行完毕释放CPU释放GIL,释放lock,此时a的值为2

  • 相关阅读:
    PMP(第六版)十大知识领域、五大项目管理过程组、49个过程矩阵
    快速开发平台分享-UCML快速开发七种武器
    敏捷开发干货-快速开发平台的主题行为模型介绍
    MACHINE LEARNING
    What is “Neural Network”
    VS打开项目或解决方案卡死,一直处于未响应状态。
    Sql Server 本地(客户端)连接服务器端操作
    阿里云服务器,Sql Server 本地连接服务器端问题记录
    <%@ Register TagPrefix="uc1" TagName="user" Src="../Control/user.ascx" %>什么意思?
    IIS网站部署后,程序常见错误记录
  • 原文地址:https://www.cnblogs.com/zhoajiahao/p/11141883.html
Copyright © 2011-2022 走看看