协程:
#定义来自牛人alex博客
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。 使用协程的目的:就是为了最大限度使用CPU,把IO操作解耦,提高程序运行速度 协程的好处:
无需线程上下文切换的开销
无需原子操作锁定及同步的开销
"原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。 缺点:
无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序 greenlet是封装好了的协程
gevent 是进一步封装了greenlet greenlet还需要通过greenlet.greenlet(func)生成greenlet类实例,只能通过gr1.swich()方法手动切换方法执行。
gevent通过gevent.spawn(func,args)生成greenlet类实例,通过gevent.joinall([])装载Greenlet实例,即可启动各个方法,并实现自动的遇到IO就切换
一般在整个当前程序前需要from gevent import monkey引入monkey包,这是个补丁,里边有monkey.patch_all()方法,是明确标记所有IO操作,遇到就切换,
主要是像socket、urllib中的IO操作不会被gevent直接发现时使用这个补丁就能发现了。
gevent需要自行安装pip install gevent
  1. 必须在只有一个单线程里实现并发
  2. 修改共享数据不需加锁
  3. 用户程序里自己保存多个控制流的上下文栈
  4. 一个协程遇到IO操作自动切换到其它协程

源生的协程
import time
import queue
def consumer(name):
print("--->starting eating baozi...")
while True:
new_baozi = yield
print("[%s] is eating baozi %s" % (name,new_baozi))
#time.sleep(1) def producer(): r = con.__next__()
r = con2.__next__()
n = 0
while n < 5:
n +=1
con.send(n)
con2.send(n)
print("\033[32;1m[producer]\033[0m is making baozi %s" %n ) if __name__ == '__main__':
con = consumer("c1")
con2 = consumer("c2")
p = producer()

利用模块greenlet写协程,简单一些了

#用greenlet来写个简单的协程,大家猜一下运行结果

import greenlet  #导入greenlet协程包

def green_func1():  #定义第一个协程用的方法
print(12)
gr2.switch() #切换到协程gr2,保存现场,再度切换回来时,从这里开始
print(34)
gr2.switch() #切换到协程gr2,保存现场,再度切换回来时,从这里开始 def green_func2(): #定义第二个协程用的方法
print(56)
gr1.switch() #切换回协程gr1,保存现场,再度切换回来时,从这里开始
print(78) gr1=greenlet.greenlet(green_func1) #定义第一个协程,装入方法green_func1方法,并启动协程gr1
gr2=greenlet.greenlet(green_func2) #定义第二个协程,装入方法green_func2方法,并启动协程gr2 gr1.switch() #手动切换到协程gr1开始执行。因为没有执行过,所以切换时,从函数开头执行

来个自动的切换吧,这才是真正的写法:

#写个协程抓个网页看看
import gevent,time #引入协程模块
from urllib import request
from gevent import monkey #引入协程模块下的monkey补丁模块
monkey.patch_all() #使用monkey模块下的patch_all()方法,作用是:在每个urllib模块的IO操作前增加标记,来明确协程切换时机 def f_get(url): #定义使用协程的方法,
print("GET %s"%url)
resp=request.urlopen(url)
data=resp.read()
print("%d bytes recevied from %s"%(len(data),url)) urls=[
"https://www.baidu.com/",
"https://github.com/",
"https://hub.docker.com/",
"https://www.yahoo.com/"
] print("同步获取:")
ss_time=time.time()
for u in urls:
f_get(u)
print("同步耗时:%s"%(time.time()-ss_time)) print("协程异步获取:")
async_time=time.time()
gevent.joinall([ #定义协程的启动,需要传入一个gevent.spawn(其实就是Greenlet类的实例)列表
gevent.spawn(f_get,"https://www.baidu.com/"),
gevent.spawn(f_get,"https://github.com/"),
gevent.spawn(f_get,"https://hub.docker.com/"),
gevent.spawn(f_get,"https://www.yahoo.com/")
])
print("协程异步耗时:%s"%(time.time()-async_time)) print("循环生成Greenlet实例变成列表协程异步获取:")
gl=[]
for uu in urls:
gl.append(gevent.spawn(f_get,uu))
async_time=time.time()
gevent.joinall(gl)#定义协程的启动,需要传入一个gevent.spawn(其实就是Greenlet类的实例)列表
print("协程异步耗时:%s"%(time.time()-async_time))

python3.x Day6 协程的更多相关文章

  1. Python3的原生协程(Async/Await)和Tornado异步非阻塞

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_113 我们知道在程序在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞,而协程作为一种用户态的轻量级线程,可以帮我们解决 ...

  2. 运筹帷幄决胜千里,Python3.10原生协程asyncio工业级真实协程异步消费任务调度实践

    我们一直都相信这样一种说法:协程是比多线程更高效的一种并发工作方式,它完全由程序本身所控制,也就是在用户态执行,协程避免了像线程切换那样产生的上下文切换,在性能方面得到了很大的提升.毫无疑问,这是颠扑 ...

  3. 小议Python3的原生协程机制

    此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在最近发布的 Python 3.5 版本中,官方正式引入了 async/await关键字.在 asyncio ...

  4. python3 - 多线程和协程速率测试对比

    多线程和协程都属于IO密集型,我通过以下用例测试多线程和协程的实际速率对比. 实例:通过socket客户端以多线程并发模式请求不同服务器端(这里服务器端分2种写法:第一种服务器通过协程实现,第二种服务 ...

  5. Python3 协程相关 - 学习笔记

    什么是协程 协程的优势 Python3中的协程 生成器 yield/send yield + send(利用生成器实现协程) 协程的四个状态 协程终止 @asyncio.coroutine和yield ...

  6. 再议Python协程——从yield到asyncio

    协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...

  7. 关于Python的协程问题总结

    协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...

  8. Python3 与 C# 并发编程之~ 协程篇

      3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...

  9. python3通过gevent.pool限制协程并发数量

    协程虽然是轻量级的线程,但到达一定数量后,仍然会造成服务器崩溃出错.最好的方法通过限制协程并发数量来解决此类问题. server代码: #!/usr/bin/env python # -*- codi ...

随机推荐

  1. (九)SpringBoot整合redis框架

    二:添加Redis依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...

  2. Mantis优化改造(技术篇)

    为什么要写这篇? 既然都过去这么久了,都回忆不起来了,为什么还要整理出来这篇文章呢? 这还要追溯到2018年3月份. 当时换工作,面试了国内某知名电视厂商. 简历上面写了我优化改造了bug管理系统ma ...

  3. PostgreSQL - 允许远程访问的设置方法

    原文转载至:PostgreSQL 允许远程访问设置方法 安装PostgreSQL数据库之后,默认是只接受本地访问连接.如果想在其他主机上访问PostgreSQL数据库服务器,就需要进行相应的配置. 配 ...

  4. bzoj 4456 [Zjoi2016]旅行者

    题面 https://www.lydsy.com/JudgeOnline/problem.php?id=4456 题解 分治 设当前work的区间为(x1,y1,x2,y2) 我们将长边分成两半 不妨 ...

  5. 浅谈算法——KMP

    KMP是啥?KMP当然是KMPlayer的简称啦 KMP算法是用来解决字符串匹配的一种算法,由D.E.Knuth.J.H.Morris和V.R.Pratt同时发现,然后它可以用来干啥呢?我们上个例题: ...

  6. Codeforces Round #544 (Div. 3) D. Zero Quantity Maximization

    链接:https://codeforces.com/contest/1133/problem/D 题意: 给两个数组a,b. 同时ci = ai * d + bi. 找到一个d使c数组中的0最多. 求 ...

  7. 在虚拟机里安装windows或Linux系统时,安装窗口过大按钮有时点不到解决办法(图文详解)

    不多说,直接上干货! 问题详情 解决办法 很简单快捷的解决办法,就是快捷键ALT+F7,可以拖动窗口的位置. 成功!

  8. js数据类型之判断

    js有几种类型,具体是:字符串(String).数字(Number).布尔(Boolean).数组(Array).对象(Object).空(Null).未定义(Undefined). js提供了typ ...

  9. CF622C Not Equal on a Segment

    题目链接: http://codeforces.com/problemset/problem/622/C 题目大意: 给定一个长度为n(n不超过200000)的序列,有m(m不超过200000)次询问 ...

  10. ssl证书过期问题解决

    1,ssl证书失效现象 小程序debug有如下证书无效信息: 浏览器访问https://ic-park.net:30001/indoornav/callFunction1.php 提示证书风险. 2, ...