协程

协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:

协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

协程的好处:

1.无需线程上下文切换的开销
2.无需原子操作锁定及同步的开销
3.方便切换控制流,简化编程模型
4.高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

缺点:

无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

Greenlet

from greenlet import greenlet

def test1():
print(1)
gr2.switch()
print(4)
gr2.switch()
def test2():
print(2)
gr3.switch()
print(5)
gr3.switch()
def test3():
print(3)
gr1.switch()
print(6)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr3 = greenlet(test3)
gr1.switch()

Gevent

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

import gevent

def test1():
print(1)
gevent.sleep(2)
print(4)
def test2():
print(2)
gevent.sleep(1)
print(5)
def test3():
print(3)
gevent.sleep(0)
print(6)
gevent.joinall([
gevent.spawn(test1),
gevent.spawn(test2),
gevent.spawn(test3),
])

同步与异步的性能区别

import gevent

def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(0.5)
print('Task %s done' % pid)

def synchronous():
for i in range(1,10):
task(i)

def asynchronous():
threads = [gevent.spawn(task, i) for i in range(10)]
gevent.joinall(threads)

print('Synchronous:')
synchronous()

print('Asynchronous:')
asynchronous()

上面程序的重要部分是将task函数封装到Greenlet内部线程的gevent.spawn。 初始化的greenlet列表存放在数组threads中,此数组被传给gevent.joinall 函数,后者阻塞当前流程,并执行所有给定的greenlet。执行流程只会在 所有greenlet执行完后才会继续向下走。

遇到IO阻塞时会自动切换任务

from gevent import monkey; monkey.patch_all()
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/'),
])

通过gevent实现单线程下的多socket并发

server side

import sys
import socket
import time
import gevent

from gevent import socket,monkey
monkey.patch_all()

def server(port):
s = socket.socket()
s.bind(('0.0.0.0', port))
s.listen(500)
while True:
cli, addr = s.accept()
gevent.spawn(handle_request, cli)

def handle_request(conn):
try:
while True:
data = conn.recv(1024)
print("recv:", data)
conn.send(data)
if not data:
conn.shutdown(socket.SHUT_WR)

except Exception as ex:
print(ex)
finally:
conn.close()
if __name__ == '__main__':
server(8001)

client side

import socket

HOST = 'localhost' # The remote host
PORT = 8001 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
msg = bytes(input(">>:"),encoding="utf8")
s.sendall(msg)
data = s.recv(1024)
#print(data)

print('Received', repr(data))
s.close()

python 协程学习的更多相关文章

  1. python 线程 进程 协程 学习

    转载自大神博客:http://www.cnblogs.com/aylin/p/5601969.html 仅供学习使用···· python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和 ...

  2. day-5 python协程与I/O编程深入浅出

    基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1.  什么是协程(以下内容来自维基百 ...

  3. Python协程(真才实学,想学的进来)

    真正有知识的人的成长过程,就像麦穗的成长过程:麦穗空的时候,麦子长得很快,麦穗骄傲地高高昂起,但是,麦穗成熟饱满时,它们开始谦虚,垂下麦芒. --蒙田<蒙田随笔全集> *** 上篇论述了关 ...

  4. Python协程与Go协程的区别二

    写在前面 世界是复杂的,每一种思想都是为了解决某些现实问题而简化成的模型,想解决就得先面对,面对就需要选择角度,角度决定了模型的质量, 喜欢此UP主汤质看本质的哲学科普,其中简洁又不失细节的介绍了人类 ...

  5. python协程详解,gevent asyncio

    python协程详解,gevent asyncio 新建模板小书匠 #协程的概念 #模块操作协程 # gevent 扩展模块 # asyncio 内置模块 # 基础的语法 1.生成器实现切换 [1] ...

  6. 5分钟完全掌握Python协程

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 1. 协程相关的概念 1.1 进程和线程 进程(Process)是应用程序启动的实例,拥有代码.数据 ...

  7. Python协程与JavaScript协程的对比

    前言 以前没怎么接触前端对JavaScript 的异步操作不了解,现在有了点了解一查,发现 python 和 JavaScript 的协程发展史简直就是一毛一样! 这里大致做下横向对比和总结,便于对这 ...

  8. Python 协程总结

    Python 协程总结 理解 协程,又称为微线程,看上去像是子程序,但是它和子程序又不太一样,它在执行的过程中,可以在中断当前的子程序后去执行别的子程序,再返回来执行之前的子程序,但是它的相关信息还是 ...

  9. 终结python协程----从yield到actor模型的实现

    把应用程序的代码分为多个代码块,正常情况代码自上而下顺序执行.如果代码块A运行过程中,能够切换执行代码块B,又能够从代码块B再切换回去继续执行代码块A,这就实现了协程 我们知道线程的调度(线程上下文切 ...

随机推荐

  1. Mysql学习总结(21)——MySQL数据库常见面试题

    1. 如何使用SELECT语句找到你正在运行的服务器的版本并打印出当前数据库的名称? 答:下面的语句的结果会显示服务器的版本和当前的数据库名称 mysql> SELECT VERSION(), ...

  2. UVA Foreign Exchange

    Foreign Exchange Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Your non ...

  3. 洛谷 P3671 [USACO17OPEN]Where's Bessie? 贝西在哪呢

    P3671 [USACO17OPEN]Where's Bessie? 贝西在哪呢 题目背景 农夫John正在测试一个他新发明的全自动寻找奶牛无人机,它能够照一张农场的图片然后自动找出奶牛的位置. 不幸 ...

  4. 如何成为一个偷懒又高效的Android开发人员

    我敢肯定你对这个标题肯定心存疑惑,但事实就是如此,这个标题完全适合Android开发人员.据我所知, Android程序员不情愿写 findViewById().点击事件监听等重复率较高的代码.那我们 ...

  5. Qt 3D教程(二)初步显示3D的内容

    Qt3D教程(二)初步显示3D的内容 前一篇很easy,全然就没有牵涉到3D的内容,它仅仅是我们搭建3D应用的基本框架而已,而这一篇.我们将要利用它来初步地显示3D的内容了! 本次目的是将程序中间的内 ...

  6. jquery-ui日期时间控件实现

    日期控件和时间控件为独立控件,日期时间控件要同一时候导入日期控件和时间控件的js,然后在日期控件加入时间控件显示參数,没有导入时间控件js.日期控件函数设置的时间控件參将包错 日期控件官网网址:htt ...

  7. 微软100题第51题:和为n连续正数序列

    题目:输入一个正数n,输出全部和为n连续正数序列.比如输入15,因为1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5.4-6和7-8. 方法一:记录序列长度.推断首项是否满足条 ...

  8. ubuntu升级到14.04后终端显示重叠

    系统升级后,发现这个问题非常不爽,问题不大,但有时候找不到解决方法,让人纠结好久.解决方法例如以下: 编辑->配置文件首选项->常规-> monospace 改为ubuntu mon ...

  9. 【金阳光測试】大话Android自己主动化測试--Android自己主动化系列(1)--金阳光于2013年4月份

    Android自己主动化測试框架和工具在四年多的发展日趋成熟. 从五年前的第一代自己主动化架构演进到眼下第四代(本系列讲座第7篇后将具体剖析第三代和第四代自己主动化框架)从曾经最早谷歌推崇的monke ...

  10. POJ1338 &amp; POJ2545 &amp; POJ2591 &amp; POJ2247 找给定规律的数

    POJ1338 2545 2591 2247都是一个类型的题目,所以放到一起来总结 POJ1338:Ugly Numbers Time Limit: 1000MS   Memory Limit: 10 ...