协程:
协程,又称微线程。 是一种用户态的轻量级线程(存在一个线程中,所以没有上下文切换,与同步)
无需线程上下文切换的开销
在线程中,线程切换时需要记住上下文
无需原子操作及同步的开销
没有锁了,在一个线程中所以没有锁了
3.方便切换控制流,简化编程模型
程序员自定义控制切换
4.高并发+高扩展性+低成本
ngix 就是使用协程来并发的,支持上万的并发。很合适并发
缺点:
1.本身无法利用多核cpu的优势
可以利用多进程来利用cpu的并发
2.一个阻塞了(I/O读写的时候),其他都在等待了
yield实现协程
import time import queue def consumer(name): print("--->starting eating baozi...") while True: new_baozi = yield #两个作用,返回数值,并等待,send的新数值。 print("[%s] is eating baozi %s" % (name,new_baozi)) #time.sleep(1) def producer(): next(con) #两者都可以使用 r = con2.__next__() n = 0 while n < 5: n +=1 con.send(n) con2.send(n) print(" 33[32;1m[producer] 33[0m is making baozi %s" %n ) if __name__ == '__main__': con = consumer("c1") #生成器对象,并不会进入生成器 con2 = consumer("c2") p = producer() #执行函数
这算不算协程呢?上面都没说协程的定义:
- 必须在只有一个单线程里实现并发
- 修改共享数据不需加锁
- 用户程序里自己保存多个控制流的上下文栈
- 一个协程遇到IO操作自动切换到其它协程
greentlet模块
greenlet是一个用C实现的协程模块,相比与python自带的yield,
它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator
from greenlet import greenlet
def test1():
print(12)
g2.switch()
print(34)
g2.switch()
def test2():
print(56)
g1.switch()
print(78)
if __name__ == "__main__":
g1=greenlet(test1)
g2=greenlet(test2)
g1.switch()
感觉确实用着比generator还简单了呢,但好像还没有解决一个问题,就是遇到IO操作,自动切换,对不对?
Gevent模块
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,
在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。
Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
import gevent def func1(): print('