协程的概念

  协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。(其实并没有说明白~)

我觉得单说协程,比较抽象,如果对线程有一定了解的话,应该就比较好理解了。

那么这么来理解协程比较容易:

  线程是系统级别的,它们是由操作系统调度;协程是程序级别的,由程序员根据需要自己调度。我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序;别的子程序也可以中断回来继续执行之前的子程序,这就是协程。也就是说同一线程下的一段代码<1>执行着执行着就可以中断,然后跳去执行另一段代码,当再次回来执行代码块<1>的时候,接着从之前中断的地方开始执行。

比较专业的理解是:

  协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。


yield实现协程

子程序(函数)在执行过程中可以中断去执行别的子程序;别的子程序也可以中断回来继续执行之前的子程序”,那么很容易想到Python的yield,显然yield是可以实现这种切换的。

使用yield实现协程操作例子:

#coding=utf-
#! /usr/bin/env python
# -*- coding:utf- -*-
# Author: "Zing-p"
# Date: // def consumer(name):
print("[%s] 要开始啃骨头了..." % (name))
while True:
bone = yield
print("[%s] 正在啃骨头 %s" % (name, bone)) def producer(obj1, obj2):
obj1.send(None) # 启动obj1这个生成器,第一次必须用None <==> obj1.__next__()
obj2.send(None) # 启动obj2这个生成器,第一次必须用None <==> obj2.__next__()
n =
while n < :
n +=
print("[producer] 正在生产骨头 %s" % n)
obj1.send(n)
obj2.send(n) if __name__ == '__main__':
con1 = consumer("消费者A")
con2 = consumer("消费者B")
producer(con1, con2)

输出:

[消费者A] 要开始啃骨头了...
[消费者B] 要开始啃骨头了...
[producer] 正在生产骨头
[消费者A] 正在啃骨头
[消费者B] 正在啃骨头
[producer] 正在生产骨头
[消费者A] 正在啃骨头
[消费者B] 正在啃骨头
[producer] 正在生产骨头
[消费者A] 正在啃骨头
[消费者B] 正在啃骨头
[producer] 正在生产骨头
[消费者A] 正在啃骨头
[消费者B] 正在啃骨头
[producer] 正在生产骨头
[消费者A] 正在啃骨头
[消费者B] 正在啃骨头

greenlet实现协程

Python的 greenlet就相当于手动切换,去执行别的子程序,在“别的子程序”中又主动切换回来。。。

#! /usr/bin/env python
# -*- coding:utf- -*- from greenlet import greenlet
# greenlet 其实就是手动切换;gevent是对greenlet的封装,可以实现自动切换 def test1():
print("")
gr2.switch() # 切换去执行test2
print("")
gr2.switch() # 切换回test2之前执行到的位置,接着执行 def test2():
print("")
gr1.switch() # 切换回test1之前执行到的位置,接着执行
print("") gr1 = greenlet(test1) # 启动一个协程 注意test1不要加()
gr2 = greenlet(test2) #
gr1.switch()

输出


gevent 实现协程

Gevent 是一个第三方库,可以轻松通过gevent实现协程程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

gevent会主动识别程序内部的IO操作,当子程序遇到IO后,切换到别的子程序。如果所有的子程序都进入IO,则阻塞。

#! /usr/bin/env python3
# -*- coding:utf- -*- import gevent def func1():
print("func1 running")
gevent.sleep() # 内部函数实现io操作
print("switch func1") def func2():
print("func2 running")
gevent.sleep()
print("switch func2") def func3():
print("func3 running")
gevent.sleep()
print("func3 done..") gevent.joinall([gevent.spawn(func1),
gevent.spawn(func2),
gevent.spawn(func3),
])

输出

func1 running
func2 running
func3 running
func3 done..
switch func2
switch func1

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. 四、Mosquitto 高级应用之用户配置

    本文将讲解 Mosquitto 用户机制.如果还没有搭建 Mosquitto 服务的可以参考我的另外两篇文章<< 一.Mosquitto 介绍&安装>> << ...

  2. 图练习-BFS-从起点到目标点的最短步数(sdut 2830)邻接边表

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2830 题目描述 在古老的魔兽传说中,有两个军团 ...

  3. Postman使用js获取日期

    在用postman进行接口自动化测试的时候,某个查询接口需要使用到日期参数进行请求: 假设当前日期为2018-05-07 10:30:20 ,需要传的日期为: beginTime:2018-05-01 ...

  4. webapi swagger学习笔记

    版权声明:部分摘抄其他博主朋友的博文内容,旨在分享学习,如给您带来不便,请原谅.原文地址 http://www.cnblogs.com/yanweidie/p/5709113.html#_label3 ...

  5. SV搭建验证环境

    1)首先定义纯虚类Sv_object,主要实现下边两个function: 定义local static 变量nextobjectID; 虚方法 virtual function void copy(S ...

  6. mac远程连接windows

    第一步:在Mac上安装Remote Desktop Connection 进入Microsoft Remote Desktop Connection下载安装包. 下载完成之后,双击安装包进行安装. 第 ...

  7. 去n的第一个出现的1

    实例十八:去n的第一个出现的1 方法:result=n & (n-1) 与实例十七 思路类似.实例十七是不断取1,本例只去最低位. 解释:n 0000 1111n-1 0000 1110&am ...

  8. VS添加节点

    很喜欢添加节点来减少代码的长度,方便阅读:VS快捷键和相关设置

  9. Java: war包的作用及使用方法,如何解压后缀名为war的文件

    1.什么是war文件? 如果一个Web应用程序的目录和文件非常多,那么将这个Web应用程序部署到另一台机器上,就不是很方便了,我们可以将Web应用程序打包成Web归档(WAR)文件.这个过程和把Jav ...

  10. linux常用命令:grep 命令

    Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全局正则表达 ...