协程

#线程:单线程下的并发就叫协程

# 引子:单线程下的并发,yield还记得不,也叫协程,但是意义不大,效率不高
# 如果是纯计算类型,你并发,会浪费时间,效率不高
# 所以我们要解决这个问题,遇到计算咋办,遇到IO咋办
# def producer():
#     g = consumer()
#     print(next(g))
#     for i in range(10):
#         g.send("商品%s"%(i))
#     pass
# def consumer():
#     while True:
#         data = yield
#         print("消费者收到%s"%(data))
# if __name__ == "__main__":
#     producer()

#目的:为了较少IO,让线程变为计算密集型,从而分配cpu执行,提高效率

# 优点如下:
#
# 1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
# 2. 单线程内就可以实现并发的效果,最大限度地利用cpu
# 缺点如下:
#
# 1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
# 2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
# 总结协程特点:
#
# 必须在只有一个单线程里实现并发
# 修改共享数据不需加锁
# 用户程序里自己保存多个控制流的上下文栈
# 附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))

# yield greenlet 都没有实现  都不重要
# from greenlet import greenlet
#
# def eat(name):
#     print("%s eat 1"%(name))
#     g2.switch("wusen")
#     print("%s eat 2"%(name))
#     g2.switch()
# def play(name):
#     print("%s play 1"%(name))
#     g1.switch()
#     print("%s play 2"%(name))
#
# if __name__ == "__main__":
#     g1 = greenlet(eat)
#     g2 = greenlet(play)
#     g1.switch("wusen")



#嘿嘿这是正题
# from gevent import monkey;monkey.patch_all() # 监控程序下所有的IO 一定要在文件的开头
# import gevent,time
#
# def eat(name):
#     print("%s eat 1"%(name))
#     gevent.sleep(3)
#     print("%s eat 2"%(name))
#     gevent.sleep(5)
#
# def play(name):
#     print("%s play 1"%(name))
#     gevent.sleep(8)
#
#     print("%s play 2"%(name))
#
# if __name__ == "__main__":
#     #这两个是异步提交
#     g1 = gevent.spawn(eat,"wusen")
#     g2 = gevent.spawn(play," 3ξ")
#
#     #方法一
#     g1.join()
#     g2.join()
#
#     # 方法二
#     gevent.joinall([g1,g2])





# 怎么玩呢,多进程下多线程全局协程,那你就牛逼了,效率就很快了
View Code

协程结构:
1.yield
2.greenlet
3.gevent

 

第三个才是重点:原理,让程序内部变成计算型,从而抢cpu,

from gevent import monkey;monkey.patch_all() # 监控程序下所有的IO 一定要在文件的开头
import gevent,time

def eat(name):
    print("%s eat 1"%(name))
    gevent.sleep(3)
    print("%s eat 2"%(name))
    gevent.sleep(5)

def play(name):
    print("%s play 1"%(name))
    gevent.sleep(8)
    print("%s play 2"%(name))

if __name__ == "__main__":
    #这两个是异步提交
    g1 = gevent.spawn(eat,"wusen")
    g2 = gevent.spawn(play,"")

    #方法一
    g1.join()
    g2.join()
    # 方法二
    gevent.joinall([g1,g2])

 

posted @ 2020-08-04 15:47    阅读(101)  评论(0编辑  收藏  举报