zoukankan      html  css  js  c++  java
  • 并发编程--线程

    GIL全局解释器锁

    1. GIL:全局解释器锁

    翻译:在同一个进程下开启的多线程,同一时刻只能一个线程执行,因为Cpython的内存管理不是线程安全。

    GIL全局解释器锁,本质上就是一把互斥锁,保证数据安全。

    定义:在Cpython解释器中,同一个进程下开启多线程,同一时刻只能一个线程执行,无法利用多核优势。

    1. GIL全局解释器锁的优缺点:

      优点:保证数据的安全

      缺点:单个线程下,开启多个线程,牺牲执行效率,无法实现并行,只能实现串行。

      —IO密集型下使用多线程

      —计算密集型下使用多进程

    import time
    from threading import Thread
    
    n = 100
    def task():
        global n
        m = n
        time.sleep(3)
        n = m - 1
    
    if __name__ == '__main__':
        list1 = []
        for line in range(10):
            t = Thread(target=task)
            t.start()
            list1.append(t)
    
        for t in list1:
            t.join()
    
        print(n)
    

    多线程

    IO密集型下使用多线程

    计算密集型下使用多进程

    1. IO密集型任务,每个任务4S
    • 单核:开启线程比进程节省资源.
    • 多核:
      • 多线程:开启4哥子线程:16S
      • 多进程:开启4哥进程:16S + 申请开启资源消耗的时间
    # 计算密集型任务
    def task1():
        # 计算1000000次 += 1
        i = 10
        for line in range(10000000):
            i += 1
    
    # IO密集型任务
    def task2():
        time.sleep(3)
    
    if __name__ == '__main__':
        # 1、测试多进程:
        # 测试计算密集型
        # start_time = time.time()
        # list1 = []
        # for line in range(6):
        #     p = Process(target=task1)
        #     p.start()
        #     list1.append(p)
        #
        # for p in list1:
        #     p.join()
        # end_time = time.time()
        # # 消耗时间: 0.44082188606262207
        # print(f'计算密集型消耗时间: {end_time - start_time}')
        #
        # # 测试IO密集型
        # start_time = time.time()
        # list1 = []
        # for line in range(6):
        #     p = Process(target=task2)
        #     p.start()
        #     list1.append(p)
        #
        # for p in list1:
        #     p.join()
        # end_time = time.time()
        # # 消耗时间: 0.44082188606262207
        # print(f'IO密集型消耗时间: {end_time - start_time}')
    
    1. 计算密集型,每个任务4S
    • 单核:开启线程比进程节省资源
    • 多核:
      • 多线程:开启4个子进程–>16S
      • 多进程:开启多个进程–>4s

    计算密集型:多进程

    ​ 假设100份原材料同时到达工厂,聘请100个人同时制造,效率最高

    IO密集型:多线程

    假设100份原材料,只有40份了,其他还在路上,聘请40个人同时制造

    # 测试计算密集型
        start_time = time.time()
        list1 = []
        for line in range(6):
            p = Thread(target=task1)
            p.start()
            list1.append(p)
    
        for p in list1:
            p.join()
        end_time = time.time()
        # 消耗时间: 0.44082188606262207
        print(f'计算密集型消耗时间: {end_time - start_time}')
    
        # 测试IO密集型
        start_time = time.time()
        list1 = []
        for line in range(6):
            p = Thread(target=task2)
            p.start()
            list1.append(p)
    
        for p in list1:
            p.join()
        end_time = time.time()
        # 消耗时间: 0.44082188606262207
        print(f'IO密集型消耗时间: {end_time - start_time}')
    

    协程

    进程:资源单位

    线程:执行单位

    协程:单线程下实现并发

    • 在IO密集型的情况下,使用协程能提高最高的效率.
    • 注意:协程不是任何单位,只是一个程序员YY出来的东西

    总结:多进程-->多线程-->让每个线程都实现协程.(但线程下实现并发)

    协程的目的:手动实现‘遇到IO切换+保存状态‘去骗操作系统,让操作系统误以为没有IO操作,将CPU的执行权限给你。

    '''
    # import time
    # def task1():
    #     time.sleep(1)
    #
    # def task2():
    #     time.sleep(3)
    #
    # def task3():
    #     time.sleep(5)
    #
    # def task4():
    #     time.sleep(7)
    #
    # def task5():
    #     time.sleep(10)
    
    
    # 遇到IO切换(gevent模块) + 保存状态
    # def func():
    #     yield
    
    from gevent import monkey  # 猴子补丁
    monkey.patch_all()  # 监听所有的任务是否有IO操作
    from gevent import spawn  # spawn(任务)
    from gevent import joinall
    import time
    
    def task1():
        print('start from task1...')
        time.sleep(1)
        print('end from task1...')
    
    def task2():
        print('start from task2...')
        time.sleep(3)
        print('end from task2...')
    
    def task3():
        print('start from task3...')
        time.sleep(5)
        print('end from task3...')
    
    
    if __name__ == '__main__':
    
        start_time = time.time()
        sp1 = spawn(task1)
        sp2 = spawn(task2)
        sp3 = spawn(task3)
        # sp1.start()
        # sp2.start()
        # sp3.start()
        # sp1.join()
        # sp2.join()
        # sp3.join()
        joinall([sp1, sp2, sp3])
    
        end_time = time.time()
    
        print(f'消耗时间: {end_time - start_time}')
    
    我把月亮戳到天上 天就是我的 我把脚踩入地里 地就是我的 我亲吻你 你就是我的
  • 相关阅读:
    ADSL自动更换IP的方法
    css框架 一个可控性强的css+xhtml页面布局生成器。
    Linux环境配置之LAMP搭建(源码安装)
    PHP小技巧
    Google首页电吉他源代码下载
    Jquery 插件可以用来操作定界窗,将在定界窗内选取的项目放到父窗口内
    今天見鬼了
    今天闲着没事去公园玩了一下,随手拍了几张
    PHP利用PHPMailer组件的Gmail发信能力发送电子邮件
    端午节放假去台湾中部山区野餐时照的
  • 原文地址:https://www.cnblogs.com/zhulipeng-1998/p/12863897.html
Copyright © 2011-2022 走看看