协程与异步io 协程与线程的区别
协程,又称微线程,纤程。英文名coroutine。python对协程的支持是通过generator实现的。在generator中,我们不但可以通过for循环来迭代,还可以不断调用next()函数获取由yield语句返回的下一个值。但是python的yield不但可以返回一个值,它还可以接收调用者发出的参数。yield其实是终端当前的函数,返回给调用方。python3中使用yield来实现range,节省内存,提高性能,懒加载的模式。
asyncio是python3.4版本引入的标准库,直接内置了对异步io的支持。
从python3.5开始引入了新的语法async和await,用来简化yield的语法:
importasyncio
importthreading
asyncdefcompute(x,y):
print("compute%s+%s..."%(x,y))
print(threading.current_thread().name)
awaitasyncio.sleep(x+y)
returnx+y
asyncdefprint_sum(x,y):
result=awaitcompute(x,y)
print("%s+%s=%s"%(x,y,result))
print(threading.current_thread().name)
if__name__=="__main__":
loop=asyncio.get_event_loop()
tasks=[print_sum(1,2),print_sum(3,4)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
线程是内核进行抢占式的调度的,这样就确保了每个线程都有执行的机会。而coroutine运行在同一个线程中,由语言的运行时中的eventloop(事件循环)来进行调度。和大多数语言一样,在python中,协程的调度是非抢占式的,也就是说一个协程必须主动让出执行机会,其他协程才有机会运行。
让出执行的关键字就是await。也就是说一个协程如果阻塞了,持续不让出cpu,那么整个线程就卡住了,没有任何并发。
ps:作为服务端,eventloop最核心的就是io多路复用技术,所有来自客户端的请求都由io多路复用函数来处理;作为客户端,eventloop的核心在于利用future对象延迟执行,并使用send函数激发协程,挂起,等待服务端处理完成返回后再调用callback函数继续下面的流程
go语言的协程是语言本身特性,erlang和golang都是采用了csp(communicatingsequentia**rocesses)模式(python中的协程是eventloop模型),但是erlang是基于进程的消息通信,go是基于goroutine和channel的通信。
python和go都引入了消息调度系统模型,来避免锁的影响和进程/线程开销大的问题。
协程从本质上来说是一种用户态的线程,不需要系统来执行抢占式调度,而是在语言层面实现线程的调度。因为协程不再使用共享内存/数据,而是使用通信来共享内存/锁,因为在一个超级大系统里具有无数的锁,共享变量等等会使得整个系统变得无比的臃肿,而通过消息机制来交流,可以使得每个并发的单元都成为一个独立的个体,拥有自己的变量,单元之间变量并不共享,对于单元的输入输出只有消息。开发者只需要关心在一个并发单元的输入与输出的影响,而不需要再考虑类似于修改共享内存/数据对其它程序的影响。
协程与线程的区别
协程和线程密切相关,协程可以认为是运行在线程上的代码块,协程提供的挂起操作会使协程暂停执行,而不会导致线程阻塞。
协程又是一种轻量级资源,即使创建了上千个协程,对于系统来说也不是很大的负担,但如果在程序中创建上千个线程,那系统可真就压力山大了。可以说,协程的设计方式极大地提高了线程的使用率。
unity协程(coroutine)
1、协程不是线程,也不是异步执行的。
2、协程和monobehaviour的update函数一样,也是在mainthread中执行的。
3、使用协程你不用考虑同步和锁的问题。
4、协程可以被yieldreturn在当前帧进行打断,到下一帧后可以继续从被打断的地方继续运行。
5、协程是每帧的lateupdate()后去运行的。
1、一个collection要支持foreach方式的遍历,必须实现ienumerable接口(亦即,必须以某种方式返回ienumeratorobject)。
2、ienumeratorobject具体实现了iterator(通过movenext(),reset(),current)。
3、从这两个接口的用词选择上,也可以看出其不同:ienumerable是一个声明式的接口,声明实现该接口的class是“可枚举(enumerable)”的,但并没有说明如何实现枚举器(iterator);ienumerator是一个实现式的接口,ienumeratorobject就是一个iterator。
4、ienumerable和ienumerator通过ienumerable的getenumerator()方法建立了连接,client可以通过ienumerable的getenumerator()得到ienumeratorobject,在这个意义上,将getenumerator()看作ienumeratorobject的factorymethod也未尝不可。
1、在程序中调用stopcoroutine()方法只能终止以字符串形式启动(开始)的协程
2、多个协程可以同时运行,它们会根据各自的启动顺序来更新
3、协程可以嵌套任意多层
4、如果你想让多个脚本访问一个协程,那么你可以定义静态的协程
5、协程不是多线程(尽管它们看上去是这样的),它们运行在同一线程中,跟普通的脚本一样
6、如果你的程序需要进行大量的计算,那么可以考虑在一个随时间进行的协程中处理它们
7、ienumerator类型的方法不能带ref或者out型的参数,但可以带被传递的引用
8、目前在unity中没有简便的方法来检测作用于对象的协程数量以及具体是哪些协程作用在对象上
协程和线程区别是什么?
协程多与线程进行比较
1)一个线程可以多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核cpu。
2)线程进程都是同步机制,而协程则是异步
3)协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态