• 多线程--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

  • 相关阅读:
    ftp
    vmware虚拟机如何安装ubuntu14.10系统
    第1章 初识java----Java简介
    fiddler
    Program Files 与Program Files (x86)
    跟我一起认识axure(三)
    React-FlipOver-Counter(日历翻页)
    vue2-vux-fitness-project
    cloud-music
    跟我一起认识axure(二)
  • 原文地址:https://www.cnblogs.com/zhoajiahao/p/11141883.html
Copyright © 2020-2023  润新知