协程:又称为微线程,英文名称Coroutine。

作用:它拥有自己的寄存器上下文和栈,能保留上一次调用时的状态,可以随时暂停程序,随时切换回来。

优点:

•无需线程上下文切换的开销
•无需原子操作锁定及同步的开销  

•方便切换控制流,简化编程模型
•高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理

缺点:
•无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上
•进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序


使用yield实现协程:

defg(name):print("startingproduct....")whileTrue:baozi=yield#程序暂停等待nextprint("{}iseating{}...".format(name,baozi))defp():conn.__next__()#实例conn启动yieldconn2.__next__()#实例conn2启动yieldi=0whilei<5:i+=1print("product:{}".format(i))conn.send(i)#向yield发送数据,yield恢复,并自动执行nextconn2.send(i)#向yield发送数据,yield恢复,并自动执行nextconn=g("laoda")#创建实例connconn2=g("laoer")#创建实例conn2product=p()#启动函数p



使用greenlet实现协程:不是python自带模块,需要安装

创建协程对象的方法其实有两个参数”greenlet(run=None, parent=None)”。参数”run”就是其要调用的方法,比如上例中的函数test1()和test2();参数”parent”定义了该协程对象的父协程,也就是说,greenlet协程之间是可以有父子关系的。如果不设或设为空,则其父协程就是程序默认的”main”主协程。

fromgreenletimportgreenletdeftest1():print(1)t2.switch()#函数暂停,切换到t2print(2)deftest2():print(3)t1.switch()#函数暂停,切换到t1print(4)t1=greenlet(test1)#test1生成greenlet对象t2=greenlet(test2)#test2生成greenlet对象t1.switch()



使用gevent实现协程:第三方库,需要安装

实现了异步I/O,操作

方法
参数
作用
示例
spawn(func,func_args)

func:加入gevent的函数名

func_args:函数参数

把函数,创建协程实例

joinall[spawn_list]
spawn_list:spawn方法列表

把创建的协程实例添加到异步列表

等待列表中的所有实例执行完毕


sleep(time)
time:时间(秒)
交出CPU控制权,时间为秒

getcurrent()
获取当前协程内存地址

fromgeventimportgeventimportrandomdefcreat(num):wait_time=random.Randomint(0,num)gevent.sleep(wait_time)print("{}waitdone!".format(gevent.getcrrent()))gevent_list=[]foriinrange(20):gevent_list.append(gevent.spawn(creat,i))gevent.joinall(gevent_list)#Socket并发:(未测试)importgeventimportsocketclassserver(object):def__int__(self,ip,port,*args):self.server_in=socket.socket()self.server_in.bind(ip,port)self.server_in.listen(100)#self.spawn_list=[]defrun(self):client_spawn=[]whileTrue:conn,addr=self.server_in.accept()client_spawn.append(gevent.spawn(handler,conn))gevent.joinall(client_spawn)defhandler(self,conn):whileTrue:recv_data=conn.recv(1024)ifrecv_data='exit':conn.shutdown(socket.SHUT_WR)breakprint("recv:".format(recv_data))conn.send(recv_data.upper())

http://python.jobbole.com/86481/

协程详解