协程:

  协程,又称微线程。  是一种用户态的轻量级线程(存在一个线程中,所以没有上下文切换,与同步)

无需线程上下文切换的开销

  在线程中,线程切换时需要记住上下文

无需原子操作及同步的开销

  没有锁了,在一个线程中所以没有锁了

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("\033[32;1m[producer]\033[0m is making baozi %s" %n ) if __name__ == '__main__':
con = consumer("c1") #生成器对象,并不会进入生成器
con2 = consumer("c2")
p = producer() #执行函数 这算不算协程呢?上面都没说协程的定义:
  
  1. 必须在只有一个单线程里实现并发
  2. 修改共享数据不需加锁
  3. 用户程序里自己保存多个控制流的上下文栈
  4. 一个协程遇到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('\033[31;1m李闯在跟海涛搞...\033[0m')
gevent.sleep(2) #模拟I/O阻塞
print('\033[31;1m李闯又回去跟继续跟海涛搞...\033[0m') def func2():
print('\033[32;1m李闯切换到了跟海龙搞...\033[0m')
gevent.sleep(3)
print('\033[32;1m李闯搞完了海涛,回来继续跟海龙搞...\033[0m')
if __name__=="__main__":
gevent.joinall([
gevent.spawn(func1,),
gevent.spawn(func2, )
])

同步与异步比较

import gevent

def task(pid):
gevent.sleep(0.5)
print('Task %s done' % pid) def synchronous():
for i in range(10):
task(i) def asynchronous():
threads=[gevent.spawn(task,i) for i in range(10)]
gevent.joinall(threads) print('Synchronous:')
synchronous() print('Asynchronous:')
asynchronous()

遇到I/O阻塞自动切换

现在gevent模块不能检测urllib模块的 I/O了,所有要加补丁

from gevent import monkey; monkey.patch_all()#这是一个gevent的组件,来检测I/O,快速切换。在linux下不加也可以快速切换!
import gevent
from urllib.request import urlopen def f(url):
print('GET: %s' % url)
resp = urlopen(url)
data = resp.read()
print('%d bytes received from %s.' % (len(data), url)) gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://www.yahoo.com/'),
gevent.spawn(f, 'https://github.com/'),
])

python 之协程的更多相关文章

  1. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  2. 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

    本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...

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

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

  4. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  5. 【Python】协程

    协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在 ...

  6. Python之协程(coroutine)

    Python之协程(coroutine) 标签(空格分隔): Python进阶 coroutine和generator的区别 generator是数据的产生者.即它pull data 通过 itera ...

  7. python的协程和_IO操作

    协程Coroutine: 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行. 注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点 ...

  8. python 3 协程函数

    python 3 协程函数 1:把函数的执行结果封装好__iter__和__next__,即得到一个迭代器 2:与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yiel ...

  9. Python之协程函数

    Python之协程函数 什么是协程函数:如果一个函数内部yield的使用方法是表达式形式的话,如x=yield,那么该函数成为协程函数. def eater(name): print('%s star ...

  10. 多任务-python实现-协程(2.1.11)

    多任务-python实现-协程(2.1.11) 23/100 发布文章 qq_26624329 @ 目录 1.概念 2.迭代器 1.概念 协程与子例程一样,协程(coroutine)也是一种程序组件. ...

随机推荐

  1. And Then There Was One(约瑟夫问题变形)

    题目链接:http://poj.org/problem?id=3517 And Then There Was One Time Limit: 5000MS   Memory Limit: 65536K ...

  2. [学习OpenCV攻略][008][Canny边缘检测]

    cvGetSize(输入图片) 得到输入图片的大小 cvCanny(输入图片,输出图片,lowThresh,highThresh,aperture) 把输入图片按设定光圈值进行Canny边缘检测,然后 ...

  3. Spider_Man_3 の selenium

    一:介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作, ...

  4. jquery的done和then区别

    jquery的deferred对象的done方法和then方法都能实现链式调用,但是他们的作用是有区别的,then方法中如果你传递的方法有返回值,那么他会传递给下一个链式调用的方法.而done方法与此 ...

  5. 程序员之殇 —— (The Beginning of the End)噩梦、崩坏

    Look at all those faces out there (当我环视周遭的一张张脸孔) We are so different(我们是如此的不同) But we have one thing ...

  6. Unity 小笔记

    1,Time.deltatime放在Update和fixedupdate中得到的值是不一样的.还以为是通过两个值来获取. 2,VR中绘制射线可以使用LineRender. 3,Unity中判断一个东西 ...

  7. sublime如何实现函数折叠

    Ctrl+Shift+[ 折叠代码 Ctrl+Shift+] 展开代码 Ctrl+KT 折叠属性 Ctrl+K0 展开所有

  8. HTML面试

    ------------------------------------------------------- 行列 td tr ol -------------------------------- ...

  9. web组件开发入门

    本文是学习慕课网阿当大话西游之WEB组件后的一个总结. 组件的分类 1 框架组件:依赖于某种框架的组件 2 定制组件:根据公司业务定制的组件 3 独立组件:不依赖框架的组件 定义和加载组件 解决css ...

  10. CPU频率

    CPU频率 CPU频率,就是CPU的时钟频率,简单说是CPU运算时的工作的频率(1秒内发生的同步脉冲数)的简称. 概念 CPU频率,就是CPU的时钟频率,简单说是CPU运算时的工作的频率(1秒内发生的 ...