zoukankan      html  css  js  c++  java
  • 线程与进程锁

    GIL全局解释器锁

    Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。在多线程环境中,Python 虚拟机按以下方式执行:

    1. 设置 GIL;
    2. 切换到一个线程去运行;
    3. 运行指定数量的字节码指令或者线程主动让出控制(可以调用 time.sleep(0));
    4. 把线程设置为睡眠状态;
    5. 解锁 GIL;
    6. 再次重复以上所有步骤。

    在调用外部代码(如 C/C++扩展函数)的时候,GIL将会被锁定,直到这个函数结束为止(由于在这期间没有Python的字节码被运行,所以不会做线程切换)编写扩展的程序员可以主动解锁GIL。

    线程锁

    from threading import Thread,Lock
    x = 0
    mutex = Lock()
    def task():
        global x
        # mutex.acquire()
        for i in range(200000):
            x = x+1
            # t1 的 x刚拿到0 保存状态 就被切了
            # t2 的 x拿到0 进行+1       1
            # t1 又获得运行了  x = 0  +1  1
            # 思考:一共加了几次1? 加了两次1 真实运算出来的数字本来应该+2 实际只+1
            # 这就产生了数据安全问题.
        # mutex.release()
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t3 = Thread(target=task)
        t1.start()
        t2.start()
        t3.start()
        t1.join()
        t2.join()
        t3.join()
        print(x)
    C:UsersAdministratorAppDataLocalProgramsPythonPython36python.exe D:/python/9.18/02线程锁.py
    289103
    
    数据量较大时用线程就会出现数据遗失问题,所以我们要加线程锁,保证数据的安全
    

    死锁问题

    from threading import Thread,Lock
    mutex1 = Lock()
    mutex2 = Lock()
    import time
    class MyThreada(Thread):
        def run(self):
            self.task1()
            self.task2()
        def task1(self):
            mutex1.acquire()
            print(f'{self.name} 抢到了 锁1 ')
            mutex2.acquire()
            print(f'{self.name} 抢到了 锁2 ')
            mutex2.release()
            print(f'{self.name} 释放了 锁2 ')
            mutex1.release()
            print(f'{self.name} 释放了 锁1 ')
        def task2(self):
            mutex2.acquire()
            print(f'{self.name} 抢到了 锁2 ')
            time.sleep(1)
            mutex1.acquire()
            print(f'{self.name} 抢到了 锁1 ')
            mutex1.release()
            print(f'{self.name} 释放了 锁1 ')
            mutex2.release()
            print(f'{self.name} 释放了 锁2 ')
    for i in range(3):
        t = MyThreada()
        t.start()
    # 两个线程
    # 线程1拿到了(锁头2)想要往下执行需要(锁头1),
    # 线程2拿到了(锁头1)想要往下执行需要(锁头2)
    # 互相都拿到了彼此想要往下执行的必需条件,互相都不放手里的锁头,这样我们的程序就会卡在这。
    

    信号量

    from threading import Thread,currentThread,Semaphore
    import time
    def task():
        sm.acquire()
        print(f'{currentThread().name} 在执行')
        time.sleep(3)
        sm.release()
    sm = Semaphore(5)
    for i in range(15):
        t = Thread(target=task)
        t.start()
    ## 5个数据一组打印,相当于一个进程池
    

    计算密集型问题用多进程

    io密集型问题用多线程

  • 相关阅读:
    0:一种过滤机制的MobileMenuList
    MobileMenuImage
    (转)How To Kill runaway processes After Terminating Concurrent Request
    fnd_profile.value('AFLOG_ENABLED')的取值 和配置文件相关SQL
    供应商 银行 SQL (转自ITPUB)
    重启并发管理器
    定义并发请求时 业务实体值集显示没有值数据
    Oracle EBS环境下查找数据源(OAF篇)
    查看在线EBS用户的相关信息
    转,Oracle中关于处理小数点位数的几个函数,取小数位数,Oracle查询函数
  • 原文地址:https://www.cnblogs.com/oxtime/p/11542358.html
Copyright © 2011-2022 走看看