zoukankan      html  css  js  c++  java
  • GIL:全局解释器锁 VS 用户程序锁

    既然有了GIL锁,CPython还要多线程干什么?

    '''
    GIL:全局解释器锁的来历
    四核:同一时刻真正有四个任务在运行,多核的意义在于此
    单核:看上去是并发的,因为进行了上下文切换,单核永远是串行的,并发是假象
    CPython中不论有多少核,只有一个核心的CPU资源被使用,因为同一时间只有一个线程能拿到GIL锁。
    为什么这样设计呢?CPython的线程是调用操作系统的c语言的原生线程,该线程不是线程安全的。balabalabala...
    ===================官方解释======================
    在CPython中,全局解释器锁或GIL是一个互斥锁,
    这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。
    (然而,由于GIL的存在,其他特征已经发展成依赖于这个锁形成的线程安全环境)
    =================================================
    由于GIL是全局的,所以在多线程(多核)时,线程需满足两个条件才能执行
    1、被操作系统调度出来【操作系统允许它占用CPU】 2、获取到GIL锁【CPython解释器允许它执行指令】
    怎样避免GIL影响性能?就是减少GIL锁对线程的影响
    1、在单核机器上Python和其他语言一样,“多线程”只是是假象实际上还是单线程。第2条总能满足,性能没有影响
    2、在多核机器上Python只有一个核心在使用。因为多核多线程中,同时只有一个线程申请到GIL。所以要尽量减少
       对GIL的申请,例如:全IO密集型任务时才使用多线程,
       避免在计算密集型任务中使用Python的多线程(因为计算需要CPU资源,会频繁申请GIL锁,造成其他线程等待)
    ================================================
    用户程序锁:
    还有一个锁,用户程序锁,跟GIL没有关系。这个锁是保证某个全局变量的修改必须是串行的
    假设有全局变量num=0,线程作用是对num执行加1的操作。
    在线程调度的时候,A线程获取到num=0,A执行到一半,CPU执行B线程,
    B线程将num修改num=1,CPU继续执行A线程,A线程执行完毕,将num修改成1,而num在AB线程执行完其实应该为2
    此时就应该对num变量加锁。这个锁就是用户程序锁,这个锁不同于GIL锁。GIL锁是同一时间只能有一个线程使用
    CPU资源,要保证同一时间只有一个线程访问某块数据就需要“用户程序锁”
    =====================================================
    在Python2.x版本+某些操作系统里不加用户程序锁会导致结果不准。
    在Python3.x版本+某些操作系统里不确定是否有同样的问题,但是最好加上。
    '''
    import threading
    import time
    
    lock = threading.Lock()
    class Foo:
        num = 0
        @classmethod
        def run(cls):
            time.sleep(2)
            lock.acquire()
            cls.num += 1
            lock.release()
    thread_objs = []
    for i in range(20):
        thread_objs.append(threading.Thread(target=Foo.run, args=()))
    start_time = time.time()
    for i in thread_objs:
        i.start()
    for i in thread_objs:
        i.join()
    print(Foo.num)     # 20
    print(time.time()-start_time)  #  2.0051145553588867
  • 相关阅读:
    Paint类的介绍
    缓存淘汰算法之LRU
    Android SurfaceView实战 打造抽奖转盘
    android中scrollTo和scrollBy的理解
    Android View.onMeasure方法的理解
    Android Context 上下文 你必须知道的一切
    Android Animation简述
    Markdown 语法说明
    理解Java虚拟机体系结构
    Java集合框架:HashMap
  • 原文地址:https://www.cnblogs.com/staff/p/9657370.html
Copyright © 2011-2022 走看看