zoukankan      html  css  js  c++  java
  • GIL,queue,进程池与线程池

    GIL

    1.什么是GIL(这是Cpython解释器)

             GIL本质就是一把互斥锁,既然是互斥锁,原理都是一样的,都是让多个并发线程同一时间只能有一个执行

             即:有了GIL的存在,同一进程内的多个线程同一时刻只能有一个在运行,意味着Cpython中一个进程下的多个线程无法实现并行,所以就无法利用多核优势,但不影响并发的实现

             GIL可以被比喻成执行权限,同一进程下的所有线程,想要执行都需要先抢执行权限

    2.为何要有GIL

             因为Cpython解释器自带垃圾回收机制不是线程安全的

    3.如何用

             GIL vs 自定义互斥锁

                      GIL相当于执行权限,会在任务无法执行的情况下,被强行释放

                      自定义互斥锁即便是无法执行,也不会自动释放

    4.有两种并发解决方案:

             多进程:计算密集型

             多线程:IO密集型

    线程queue

    #1.队列:先进先出
    q=queue.Queue(3)
    q.put(1)
    q.put(2)
    q.put(3)
    
    print(q.get())
    print(q.get())
    print(q.get())
    
    #2.堆栈:先进后出
    q=queue.LifoQueue()
    q.put(1)
    q.put(2)
    q.put(3)
    print(q.get())
    print(q.get())
    print(q.get())
    
    #3. 优先级队列:优先级高先出来,数字越小,优先级越高
    q=queue.PriorityQueue()
    q.put((3,'data1'))
    q.put((-10,'data2'))
    q.put((11,'data3'))
    
    print(q.get())
    print(q.get())
    print(q.get())

    进程池与线程池

    1.什么时候用池

             池的功能是限制启动的进程或线程数

             什么时候应该限制?

                      当并发的任务数远远超过了计算机的承受能力时,即无法一次性开启过多的进程数或线程数时,就应该使用池的概念,将开启的进程数或线程数限制在计算机可承受的范围内。

    2.同步vs异步

             同步、异步指的是提交任务的两种方式

             同步:提交任务后就在原地等待,直到任务运行完毕后拿到任务的返回值,再继续运行下一行代码

             异步:提交完任务(绑定一个回调函数)后根本就不在原地等待,直接运行下一行代码,等到任务有返回值后会自动触发回调函数

    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    import os,time,random 
    
    def task(n):
        print('%s run...' %os.getpid())
        time.sleep(5)
        return n**2
    
    def parse(future):
        time.sleep(1)
        res=future.result()
        print('%s 处理了 %s' %(os.getpid(),res))
    
    if __name__ == '__main__':
        pool=ProcessPoolExecutor(4)
        start=time.time()
        for i in range(1,5):
            future=pool.submit(task,i)
            future.add_done_callback(parse) # parse会在futrue有返回值时立刻触发,并且将future当作参数传给parse
        pool.shutdown(wait=True)
        stop=time.time()
        print('',os.getpid(),(stop - start))

    线程池只需要将pool=ProcessPoolExecutor(4)改成pool = ThreadPoolExecutor(4)即可,在使用回调时,多进程是用主进程来执行回调的,而多线程是哪个线程闲着就由哪个线程来执行

  • 相关阅读:
    MVP Summit 2008 照片纪实(三) 922公里,目标拉斯维加斯
    Cool 给你的Visual Studio 添加音乐
    DB2 9 使用拓荒(733 考试)认证指南,第 4 部分: 嵌入式 SQL 编程(2)
    DB2 9 运用开拓(733 考试)认证指南,第 3 部分: XML 数据行使(6)
    DB2 9 运用开辟(733 考试)认证指南,第 3 部门: XML 数据独霸(4)
    DB2 9 运用开发(733 考试)认证指南,第 3 部门: XML 数据把持(8)
    DB2 9 运用开拓(733 检修)认证指南,第 6 部分: .NET 编程(3)
    DB2 9 操纵开辟(733 测验)认证指南,第 4 局部: 嵌入式 SQL 编程(5)
    DB2 9 使用启示(733 检验)认证指南,第 3 部分: XML 数据把持(5)
    DB2 9 使用拓荒(733 检验)认证指南,第 4 部分: 嵌入式 SQL 编程(3)
  • 原文地址:https://www.cnblogs.com/luck-L/p/9321765.html
Copyright © 2011-2022 走看看