zoukankan      html  css  js  c++  java
  • 并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁

    # 并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁 
    
    # 并发:是指系统具有处理多个任务(动作)的能力
    # 并行:是指系统具有 同时 处理多个任务(动作)的能力
    
    # 同步:当进程执行到一个IO(等待外部数据)的时候,需要等待外部数据接收完
    # 异步:当进程执行到一个IO(等待外部数据)的时候,不需要等待外部数据接收完,还可以做其它的处理
    
    # GIL: 全局解释器锁 在python中,无论你启多少个线程,你有多少个cpu,python在执行的时候在同一时刻只请允许一个线程运行
    # 任务:IO密集型(python的多线程是有意义的,或使用多进程+协程) 计算密集型(python的多线程就不推荐,python就不适用了)
    
    # 同步锁
    import threading, time
    
    num = 100
    
    
    def sub():
        global num
        temp = num
        time.sleep(0.00001)
        num = temp - 1
    
    
    l = []  # 定义一个空列表
    for i in range(100):  # 循环100次
        t = threading.Thread(target=sub)  # 通过循环创建100个线程t对象并放入列表中
        t.start()
        l.append(t)
    
    for t in l:  # 循环列表,让每一个线程对象t执行join()
        t.join()
    
    print(num)  # 99 居然不是0,问题在哪里?
    
    # 因为此时是IO操作,当第一个线程取到100后要睡1秒,这时还没有减1,这时第二个线程又来取值,值还是100,只要cpu执行速度越快,所有的线程来取值时都是100,意味着100个线程都拿到num为100
    # 如果sleep(0.00001),这时最终值又会变为92。这里的值与cpu调度的各线程IO操作的时间有关,sleep时间越短,各个线程拿到num为100时的情况就越少
    # 解决方法,加上同步锁,在同一时间只允许一个线程对num操作
    import threading, time
    
    num = 100
    
    
    def sub():
        global num
    
        lock.acquire()  # 加锁
        temp = num
        time.sleep(0.00001)
        num = temp - 1
        lock.release()  # 解锁
    
    
    l = []  # 定义一个空列表
    lock = threading.Lock()  # 创建同步锁
    for i in range(100):  # 循环100次
        t = threading.Thread(target=sub)  # 通过循环创建100个线程t对象并放入列表中
        t.start()
        l.append(t)
    
    for t in l:  # 循环列表,让每一个线程对象t执行join()
        t.join()
    
    print(num)  # 0
    
    # 一个死锁的例子 第一个线程需要A锁(A锁已被第二个线程占用),第二个线程需要B锁(B锁已被第一个线程占用)。结果谁也不让造成死锁
    import threading, time
    
    
    class MyThread(threading.Thread):
    
        def actionA(self):
            A.acquire()
            print(self.name, 'gotA', time.ctime())
            time.sleep(2)
            B.acquire()
            print(self.name, 'gotB', time.ctime())
            time.sleep(2)
            B.release()
            A.release()
    
        def actionB(self):
            B.acquire()
            print(self.name, 'gotB', time.ctime())
            time.sleep(2)
            A.acquire()
            print(self.name, 'gotA', time.ctime())
            time.sleep(2)
            A.release()
            B.release()
    
        def run(self):
            self.actionA()
            self.actionB()
    
    
    if __name__ == '__main__':
        A = threading.Lock()
        B = threading.Lock()
    
        l = []
        for i in range(5):
            t = MyThread()
            t.start()
            l.append(t)
    
        for i in l:
            t.join()
        print('end...')
    
    # 解决死锁的方案,使用递归锁
    
    import threading, time
    
    
    class MyThread(threading.Thread):
    
        def actionA(self):
            r_lock.acquire()
            print(self.name, 'gotA', time.ctime())
            time.sleep(2)
            r_lock.acquire()
            print(self.name, 'gotB', time.ctime())
            time.sleep(2)
            r_lock.release()
            r_lock.release()
    
        def actionB(self):
            r_lock.acquire()
            print(self.name, 'gotB', time.ctime())
            time.sleep(2)
            r_lock.acquire()
            print(self.name, 'gotA', time.ctime())
            time.sleep(2)
            r_lock.release()
            r_lock.release()
    
        def run(self):
            self.actionA()
            self.actionB()
    
    
    if __name__ == '__main__':
        r_lock = threading.RLock()  # 这里创建的是递归锁,将原来的两把锁AB换成一把锁
        # 哪个线程拿到r_lock锁,只有等它完全释放后,其它的线程才能再拿这个锁
    
        l = []
        for i in range(5):
            t = MyThread()
            t.start()
            l.append(t)
    
        for i in l:
            t.join()
    
        print('end...')
  • 相关阅读:
    超值干货:微服务架构下如何解耦,对于已经紧耦合下如何重构?
    程序员收藏不看系列:近三万字总结Spring注解开发!
    干货收藏:6 款能挣钱的 Spring Boot 开源后台管理系统
    美团二面:你向 Mysql 数据库插入 100w 条数据用了多久?
    5分钟快速掌握阿里内部MySQL性能优化的核心技术!
    优秀!一鼓作气学会“一致性哈希”,就靠这 18 张图了
    分库分表神器 Sharding-JDBC,几千万的数据你不搞一下?
    熬夜肝出5大点,18张图带你彻底弄懂MySQL事务日志
    jdk8新特性Stream
    java多线程
  • 原文地址:https://www.cnblogs.com/dangrui0725/p/9496031.html
Copyright © 2011-2022 走看看