协程

协程目的:

1单线程下实现并发:协程

解决方案:一个任务运行的过程中把它打断(保存此时的状态)切换到另一个任务中,运行一段时间再切换回来,反复来回切换

注:并发指的是多个任务看起来是同时运行的

  并发实现的本质:切换+保存状态

  并发、并行、串行:

  并发:看起来是同时运行,切换+保存状态

  并行:真正意义上的同时运行,只有在多cpu情况下才实现并行,4个cpu能够并行4个任务

  串行:一个任务完完整整地执行完毕才运行下一个任务

例如以下程序中生产者和消费者数据的来回切换:(应用程序自己控制切换及保存状态,速度更快)

import time
def consumer():
    '''任务1:接收数据,处理数据'''
    while True:
        x=yield


def producer():
    '''任务2:生产数据'''
    g=consumer()
    next(g)
    for i in range(10000000):
        g.send(i)

start=time.time()
#基于yield保存状态,实现两个任务直接来回切换,即并发的效果
#PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
producer() #1.0202116966247559

stop=time.time()
print(stop-start)
View Code

但如果一个程序中是纯计算活的话,来回切换意义不大,如下:

# 纯计算的任务串行执行
import time
def task1():
    res=1
    for i in range(1000000):
        res+=i

def task2():
    res=1
    for i in range(1000000):
        res*=i

start=time.time()
task1()
task2()
stop=time.time()
print(stop-start)


# 纯计算的任务并发执行
import time
def task1():
    res=1
    for i in range(1000000):
        res+=i
        yield    #切换到task2

def task2():
    g=task1()
    res=1
    for i in range(1000000):
        res*=i
        next(g)   #切换到task1

start=time.time()
#基于yield保存状态,实现两个任务直接来回切换,即并发的效果
#PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
task2()
stop=time.time()
print(stop-start)

打印结果:

0.22888588905334473
0.42775511741638184

可以看出做纯计算任务并发执行的时间是串行执行的2倍,速度慢了

所以单线程下实现并发是为了提高效率,检测多个任务的IO行为,遇到IO再切到自己单线程下的另外一个任务去执行,这样就把单线程下的IO问题给尽可能多的缩减下来(相当于‘欺骗了’操作系统,在操作系统看来你一直处于工作状态,操作系统才不会把cpu拿走),这样单线程就尽可能多的处于计算过程,也就是处于就绪态。

强调:

#1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
#2. 单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)

协程优点:

#1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
#2. 单线程内就可以实现并发的效果,最大限度地利用cpu

缺点:

#1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
#2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/11779561.html