协程

协程,又称微线程,纤程。英文名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. MAC中Parallels Desktop windows忘记密码的解决办法

    由于工作或是生活,在国内的环境下我们总有些时候要用到Windows才能完成某些任务,对于不经常使用Windows的用户,相信在虚拟机上安装一个Windows是不错的选择.小编就使用了Paralles ...

  2. solr + eclipse 调试环境搭建

    1: 在官网下载对应源码 http://www.fayea.com/apache-mirror/lucene/solr/4.1.0/ 选择源码文件,如图所示: 2: 解压后目录如图所示: 在根目录下存 ...

  3. Cannot set web app root system property when WAR file is not expanded

    Cannot set web app root system property when WAR file is not expanded 在tomcat下面可以,在weblogic下面不行的处理方法 ...

  4. Max Points on a Line(直线上最多的点数)

    给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | |        o |     o | ...

  5. JS 去除字符串中的最后一个字符

    var str = 'Hello World!'; str = str.substr(0,str.length-1); alert(str);

  6. Cube Simulation zoj3429 模拟

    Description Here's a cube whose size of its 3 dimensions are all infinite. Meanwhile, there're 6 pro ...

  7. CSDN博客2014年4月24日清理缓存

    亲爱的CSDN博主们.我们将于今天(2014年4月24日)对CSDN博客频道缓存进行清理,假设您登录后发现自己的文章总数.积分.评论数.訪问数出现异常,请不要慌张.您的数据并没有丢失.将会在缓存清理完 ...

  8. FZOJ--2214--Knapsack problem(背包)

    Problem 2214 Knapsack problem Accept: 5    Submit: 8 Time Limit: 3000 mSec    Memory Limit : 32768 K ...

  9. nfs共享文件服务搭建

    网络文件共享服务器192.10.19.132yum install -y nfs-utils 在exports文件中添加的从机范围vim /etc/exports/home/nfs/ 192.10.1 ...

  10. 23.STL容器小结