• 并发编程: GIL锁、GIL与互斥锁区别、进程池与线程池的区别


    本文目录:

    一、GIL

    二、关于GIL性能的讨论

    三、计算密集测试

    四、IO密集测试

    五、GIL与互斥锁

    六、进程池

    七、进程什么时候算是空闲

    八、线程池

    一、GIL

    什么叫GIL

    全局解释器锁(GIL Global Interpreter Lock),锁就是线程里面那个锁,锁是为了避免资源竞争造成数据的错乱,python程序的执行过程,1.启动解释器进程  python.exe,
    2.解析你的py文件并执行它,每个py程序中都必须有解释器参与解释器其实就是一堆代码,相当于多个线程要调用同一个解释器代码,共享以为竞争 ,竞争就要出事,所以给解释器加锁。
    
    python 中内存管理依赖于 GC(一段用于回收内存的代码) 也需要一个线程
    除了你自己开的线程 系统还有一些内置线程   就算你的代码不会去竞争解释器  内置线程也可能会竞争
    所以必须加上锁
    
    
    当一个线程遇到了IO 同时解释器也会自动解锁  去执行其他线程  CPU会切换到其他程序
    
    
    x = obj  +1
    a = obj  +1   2
    
    x = None -1
    a = None -1  0

     

    二、关于GIL性能的讨论

    """
        解释器加锁以后
            将导致所有线程只能并发 不能达到真正的并行  意味着同一时间只有一个CPU在处理你的线程
            给你的感觉是效率低
    
        代码执行有两种状态
        阻塞 i/o 失去CPU的执行权   (CPU等待IO完成)
        非阻塞  代码正常执行 比如循环一千万次  中途CPU可能切换 很快会回来   (CPU在计算)
    
        假如有32核CPU 要处理一个下载任务  网络速度慢 100k/s  文件大小为1024kb
        如果你的代码中IO操作非常多  cpu性能不能直接决定你的任务处理速度
    
    
        案例:
            目前有三个任务 每个任务处理需一秒   获取元数据需要一小时
            3个CPU 需要 一小时1秒
            1个cpu 需要 一小时3秒
    
    
        在IO密集的程序中 CPU性能无法直接决定程序的执行速度    python就应该干这种活儿
        在计算密集的程序中  CPU性能可以直接决定程序的执行速度
    
    """

     

    三、计算密集测试

    from threading import Thread
    from multiprocessing import Process
    import time
    
    
    # 计算密集任务
    
    def task1():
        sum = 1
        for i in range(10000000):
            sum *= i
    
    
    def task2():
        sum = 1
        for i in range(10000000):
            sum *= i
    
    
    def task3():
        sum = 1
        for i in range(10000000):
            sum *= i
    
    
    def task4():
        sum = 1
        for i in range(10000000):
            sum *= i
    
    
    def task5():
        sum = 1
        for i in range(10000000):
            sum *= i
    
    
    def task6():
        sum = 1
        for i in range(10000000):
            sum *= i
    
    if __name__ == '__main__':
    
        # 开始时间
        st_time = time.time()
        # 多线程情况下
        # t1 =  Thread(target=task1)
        # t2 = Thread(target=task2)
        # t3 = Thread(target=task3)
        # t4 = Thread(target=task4)
        # t5 = Thread(target=task5)
        # t6 = Thread(target=task6)
    
        t1 = Process(target=task1)
        t2 = Process(target=task2)
        t3 = Process(target=task3)
        t4 = Process(target=task4)
        t5 = Process(target=task5)
        t6 = Process(target=task6)
    
    
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        t5.start()
        t6.start()
        #
        # t1.join()
        # t2.join()
        # t3.join()
        # t4.join()
        # t5.join()
        # t6.join()
    
        print(time.time() - st_time)

     

    四、IO密集测试

    from threading import Thread
    from multiprocessing import Process
    import time
    
    
    # 计算密集任务
    def task1():
        time.sleep(3)
    
    
    def task2():
        time.sleep(3)
    
    
    def task3():
        time.sleep(3)
    
    
    def task4():
        time.sleep(3)
    
    
    def task5():
        time.sleep(3)
    
    
    def task6():
        time.sleep(3)
    
    if __name__ == '__main__':
    
        # 开始时间
        st_time = time.time()
        # 多线程情况下
        # t1 = Thread(target=task1)
        # t2 = Thread(target=task2)
        # t3 = Thread(target=task3)
        # t4 = Thread(target=task4)
        # t5 = Thread(target=task5)
        # t6 = Thread(target=task6)
    
    
        t1 = Process(target=task1)
        t2 = Process(target=task2)
        t3 = Process(target=task3)
        t4 = Process(target=task4)
        t5 = Process(target=task5)
        t6 = Process(target=task6)
    
        t1.start()
        t2.start()
        t3.start()
        t4.start()
        t5.start()
        t6.start()
    
        # t1.join()
        # t2.join()
        # t3.join()
        # t4.join()
        # t5.join()
        # t6.join()
    
        print(time.time() - st_time)

     

    五、GIL与互斥锁

    from  threading import Thread,Lock
    import time
    
    mutex = Lock()
    num = 1
    def task():
        global num
        # print(num)
        mutex.acquire()
        temp = num
        print(temp)
        time.sleep(1)   # 当你们线程中出现io时 GIL锁就解开
        num = temp + 1
        mutex.release()  # 线程任务结束时GIL锁解开
    
    
    t1 = Thread(target=task,)
    
    t2 = Thread(target=task,)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(num)
    
    #
    # GIL 和 自定义互斥锁的区别
    # 全局锁不能保证自己开启的线程安全  但是保证解释器中的数据的安全的
    # GIL 在线程调用解释器时 自动加锁  在IO阻塞时或线程代码执行完毕时 自动解锁
    #

    六、进程池

    """
        进程池
            就是一个装进程的容器
        为什么出现
            当进程很多的时候方便管理进程
        什么时候用?
            当并发量特别大的时候  列入双十一
            很多时候进程是空闲的 就让他进入进程池  让有任务处理时才从进程池取出来使用
        进程池使用
            ProcessPoolExecutor类
            创建时指定最大进程数 自动创建进程
            调用submit函数将任务提交到进程池中
            创建进程是在调用submit后发生的
    
        总结一下:
            进程池可以自动创建进程
            进程限制最大进程数
            自动选择一个空闲的进程帮你处理任务
            遗留问题 进程什么时候算是空闲
    
    """
    import socket
    from multiprocessing import Process
    
    from concurrent.futures import ProcessPoolExecutor
    
    # 收发数据
    def task(c, addr):
        while True:
            try:
                data = c.recv(1024)
                print(data.decode("utf-8"))
                if not data:
                    c.close()
                    break
                c.send(data.upper())
            except Exception:
                print("连接断开")
                c.close()
                break
    
    if __name__ == '__main__':
    
        server = socket.socket()
    
        server.bind(("127.0.0.1",65535))
    
        server.listen(5)
    
        # 创建一个进程池   默认为CPU个数
        pool = ProcessPoolExecutor()
    
        while True:
            c,addr = server.accept()
            # p = Process(target=task,args=(c,addr))
            # p.start()
            pool.submit(task,c,addr)

     

    七、进程什么时候算是空闲

    from concurrent.futures import  ProcessPoolExecutor
    
    import os,time,random
    
    def task():
        time.sleep(random.randint(1,2))
        print(os.getpid())
    
    def run():
        pool = ProcessPoolExecutor(2)
        for i in range(30):
            pool.submit(task)
    
    if __name__ == '__main__':
        run()

    八、线程池

    from concurrent.futures import  ProcessPoolExecutor,ThreadPoolExecutor
    from threading import  current_thread
    
    import os,time,random
    
    def task():
        time.sleep(random.randint(1,2))
        print(current_thread())
    
    def run():
        # 默认为cpu核心数 * 5
        pool = ThreadPoolExecutor(3)
        for i in range(30):
            pool.submit(task)
    
    if __name__ == '__main__':
        run()
  • 相关阅读:
    3.List.Set
    2.Collection.泛型
    1.Object类.常用API
    MySQL-核心技术
    奇异的家族-动态规划
    动态规划-等和的分隔子集
    跳跃游戏-贪心
    跳跃游戏2
    爬楼梯
    组合博弈1536-S-Nim
  • 原文地址:https://www.cnblogs.com/wuzhengzheng/p/10273440.html
Copyright © 2020-2023  润新知