gevent 底层是怎么实现?app
io模型4个重要概念:异步
两类socket
#所谓同步,就是在发出一个功能调用时,在没有获得结果以前,该调用就不会返回。按照这个定义,其实绝大多数函数都是同步调用。
可是通常而言,咱们在说同步、异步的时候,特指那些须要其余部件协做或者须要必定时间完成的任务。 #举例: #1. multiprocessing.Pool下的apply #发起同步调用后,就在原地等着任务结束,根本不考虑任务是在计算仍是在io阻塞,
总之就是一股脑地等任务结束 #2. concurrent.futures.ProcessPoolExecutor().submit(func,).result() #3. concurrent.futures.ThreadPoolExecutor().submit(func,).result()
异步: 提交完任务就无论了,往下执行async
#异步的概念和同步相对。当一个异步功能调用发出后,调用者不能马上获得结果。当该异步功能完成后,
经过状态、通知或回调来通知调用者。若是异步功能用状态来通知,那么调用者就须要每隔必定时间检查一次,效率就很低。
若是是使用通知的方式,效率则很高,由于异步功能几乎不须要作额外的操做。至于回调函数,其实和通知没太多区别。 #举例: #1. multiprocessing.Pool().apply_async() #发起异步调用后,并不会等待任务结束才返回,相反,会当即获取一个临时结果(并非最终的结果,多是封装好的一个对象)。 #2. concurrent.futures.ProcessPoolExecutor(3).submit(func,) #3. concurrent.futures.ThreadPoolExecutor(3).submit(func,)
异步一般和回调机制联用,提交完任务,任务运行完后,自动触发,回调函数代码函数
阻塞:遇到io,阻塞卡主spa
#阻塞调用是指调用结果返回以前,当前线程会被挂起(如遇到io操做)。函数只有在获得结果以后才会将阻塞的线程激活。
有人也许会把阻塞调用和同步调用等同起来,实际上他是不一样的。对于同步调用来讲,不少时候当前线程仍是激活的,
只是从逻辑上当前函数没有返回而已。 #举例: #1. 同步调用:apply一个累计1亿次的任务,该调用会一直等待,直到任务返回结果为止,
但并未阻塞住(即使是被抢走cpu的执行权限,那也是处于就绪态); #2. 阻塞调用:当socket工做在阻塞模式的时候,accept(),send(),recv()是阻塞io操做,若是没有数据的状况下调用recv函数,
则当前线程就会被挂起,直到有数据为止。
非阻塞:线程
#非阻塞和阻塞的概念相对应,指在不能马上获得结果以前也会马上返回,同时该函数不会阻塞当前线程。
总结:code
#1. 同步与异步针对的是函数/任务的调用方式:同步就是当一个进程发起一个函数(任务)调用的时候,
一直等到函数(任务)完成,而进程继续处于激活状态。而异步状况下是当一个进程发起一个函数(任务)调用的时候,
不会等函数返回,而是继续往下执行当,函数返回的时候经过状态、通知、事件等方式通知进程任务完成。
#2. 阻塞与非阻塞针对的是进程或线程:阻塞是当请求不能知足的时候就将进程挂起,而非阻塞则不会阻塞当前进程
io模型5大类:对象
阻塞io模型blog
非阻塞io模型
io多路复用
异步io模型
IO发生时涉及的对象和步骤。对于一个network IO \(这里咱们以read举例\),它会涉及到两个系统对象,一个是调用这个IO的process \(or thread\),另外一个就是系统内核\(kernel\)。当一个read操做发生时,该操做会经历两个阶段:
1)等待数据准备 (Waiting for the data to be ready) 2)将数据从内核拷贝到进程中(Copying the data from the kernel to the process)