协程

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

# 引子:单线程下的并发,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," 3ξ")

    #方法一
    g1.join()
    g2.join()
    # 方法二
    gevent.joinall([g1,g2])
相关文章
|
6月前
|
存储 Java API
ntyco协程的理解
ntyco协程的理解
80 0
|
3月前
|
存储 Linux 调度
协程(coroutine)的原理和使用
协程(coroutine)的原理和使用
|
4月前
|
编译器 程序员 调度
协程问题之C++20 的协程实现是基于哪种协程模型的
协程问题之C++20 的协程实现是基于哪种协程模型的
|
5月前
|
调度 C++ 开发者
C++一分钟之-认识协程(coroutine)
【6月更文挑战第30天】C++20引入的协程提供了一种轻量级的控制流抽象,便于异步编程,减少了对回调和状态机的依赖。协程包括使用`co_await`、`co_return`、`co_yield`的函数,以及协程柄和awaiter来控制执行。它们适合异步IO、生成器和轻量级任务调度。常见问题包括与线程混淆、不当使用`co_await`和资源泄漏。例如,斐波那契生成器协程展示了如何生成序列。正确理解和使用协程能简化异步代码,但需注意生命周期管理。
90 4
|
6月前
|
前端开发 编译器 Linux
浅谈C++20 协程那点事儿
本文是 C++20 的协程入门文章,作者围绕协程的概念到协程的实现思路全方位进行讲解,努力让本文成为全网最好理解的「C++20 协程」原理解析文章。
|
数据采集 缓存 调度
协程小练习
协程小练习
|
6月前
|
C++
C/C++协程学习笔记
C/C++协程学习笔记
|
6月前
|
存储 前端开发 rax
协程学习笔记 NtyCo/libgo
协程学习笔记 NtyCo/libgo
90 0
|
6月前
|
存储 前端开发 rax
协程学习笔记
协程学习笔记
54 0
|
数据采集 调度 开发者
协程这么好,那它能完全代替线程吗?
协程这么好,那它能完全代替线程吗?
194 0
协程这么好,那它能完全代替线程吗?