GIL,queue,进程池与线程池

GILpython

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

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

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

         GIL能够被比喻成执行权限,同一进程下的全部线程,想要执行都须要先抢执行权限dom

 

2.为什么要有GIL异步

         由于Cpython解释器自带垃圾回收机制不是线程安全的函数

 

3.如何用spa

         GIL vs 自定义互斥锁线程

                  GIL至关于执行权限,会在任务没法执行的状况下,被强行释放code

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

 

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)便可,在使用回调时,多进程是用主进程来执行回调的,而多线程是哪一个线程闲着就由哪一个线程来执行

相关文章
相关标签/搜索