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密集型问题用多线程

  • 相关阅读:
    QQ邮箱接收Gmail邮件的方法
    Python连接Mysql数据库——pymysql驱动
    nodejs pm2守护进程使用
    出现次数超过一半的数
    Good Hacker——模拟&&双向队列
    poj 2481 Cows——树状数组&&python
    Navicat15破解注册机详细教程-Navicat Keygen Patch v5.6.0
    宝塔面板6.X在Docker中安装宝塔面板5.9.1 – 我是不是太闲了?
    Vue全家桶(Vue-cli、Vue-route、vuex)
    基于.net core微服务(Consul、Ocelot、Docker、App.Metrics+InfluxDB+Grafana、Exceptionless、数据一致性、Jenkins)
  • 原文地址:https://www.cnblogs.com/oxtime/p/11542358.html
Copyright © 2011-2022 走看看