8.8 协程

​ 我们都知道线程间的任务切换是由操作系统来控制的,而协程的出现,就是为了减少操作系统的开销,由协程来自己控制任务的切换

​ 协程本质上就是线程。既然能够切换任务,所以线程有两个最基本的功能:一是保存状态;二是任务切换

8.8.1 协程的特点

【优点】

  • 线程任务切换开销小,属于程序级的切换,操作系统感知不到
  • 单线程内就可以实现并发的效果,最大限度的利用CPU

【缺点】

  • 协程的本质是单线程,无法利用多核;可以一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
  • 协程是单个线程执行多个任务,一旦协程遇到阻塞,将会阻塞整个线程

【特点】

  • 必须要在单线程中实现并发
  • 修改共享数据不需要加锁
  • 用户程序内保存多个控制流的上下文栈
  • 一个协程遇到IO操作自动切换到其它协程

8.8.2 Greenlet

使用grennlet第三方库实现任务间的切换

from greenlet import greenlet

def get_money(name):
print(f"{name} get 10 $")
g2.switch('jiawen')
print(f"{name} get 20 $")
g2.switch() def buy_goods(name):
print(f"{name} buy no.1 good ")
g1.switch()
print(f"{name} buy no.2 good ")
g1.switch() if __name__ == '__main__':
g1 = greenlet(get_money)
g2 = greenlet(buy_goods) g1.switch('gailun') # switch在第一次时必须要传入参数,以后就不需要了

效率对比

from greenlet import greenlet
import time def f1():
re = 1
for i in range(10000000):
re *= i
g2.switch() def f2():
re = 1
for i in range(10000000):
re += i
g1.switch() if __name__ == '__main__':
start = time.time()
g1 = greenlet(f1)
g2 = greenlet(f2) g1.switch() # switch在第一次时必须要传入参数,以后就不需要了
print(f'{time.time()- start}') # 5.822627305984497 import time def f1():
re = 1
for i in range(10000000):
re *= i def f2():
re = 1
for i in range(10000000):
re += i start = time.time()
f1()
f2()
print(f'{time.time()- start}') # 1.041489601135254

【结论】单纯的切换,在没有IO阻塞的情况下,协程的效率反而降低

8.8.3 Gevent介绍

Gevent也是一个第三方库,主要用来实现并发同步或是异步编程,在gevent中用到的主要模式是Greenlet, Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

【方法】

​ gevent.spawn(func,*args,**kwargs) spawn括号内第一个参数是函数名,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数func,spawn是异步提交任务

​ join() 等待调用者结束

​ value() 拿到调用者的返回值

遇到IO阻塞会自动切换

import gevent

def get_money(name):
print(f"{name} get 10 $")
gevent.sleep(2) #模拟的是gevent可以识别的IO阻塞
print(f"{name} get 20 $") def buy_goods(name):
print(f"{name} buy no.1 good ")
gevent.sleep(1)
print(f"{name} buy no.2 good ") if __name__ == '__main__':
g1 = gevent.spawn(get_money,'gailun')
g2 = gevent.spawn(buy_goods,name='jiawen')
g1.join()
g2.join()
# gevent.joinall([g1,g2])
print('__main__')
# 输出
gailun get 10 $
jiawen buy no.1 good
jiawen buy no.2 good
gailun get 20 $
__main__

【注意】如果要使gevent识别所有的io阻塞,放到被打补丁者的前面或者直接写在在文件的最开头写上以下代码

rom gevent import monkey;monkey.patch_all()

应用

# 爬虫
from gevent import monkey;monkey.patch_all()
import gevent
import requests
import time def get_inf(url):
print(f'GET:{url}')
res = requests.get(url)
if res.status_code == 200:
print(f"{len(res.text)} get from {url}") if __name__ == '__main__':
start_time = time.time()
gevent.joinall(
[gevent.spawn(get_inf,'https://www.python.org/'),
gevent.spawn(get_inf,'https://www.yahoo.com/'),
gevent.spawn(get_inf,'https://github.com/'),
]
)
print(f"take {time.time()-start_time} secondes")

Python学习之协程的更多相关文章

  1. Python学习---线程/协程/进程学习 1220【all】

    Python学习---线程基础学习 Python学习---线程锁/信号量/条件变量同步1221 Python学习---同步条件event/队列queue1223 Python学习---进程 1225 ...

  2. python学习笔记 协程

    在学习异步IO模型前,先来了解协程 协程又叫做微线程,Coroutine 子程序或者成为函数,在所有语言中都是层级调用,比如a调用b,b调用c.c执行完毕返回,b执行完毕返回,最后a执行完毕返回 所以 ...

  3. python学习之-- 协程

    协程(coroutine)也叫:微线程,是一种用户态的轻量级线程,就是在单线程下实现并发的效果.优点:1:无需线程上下文切换的开销.(就是函数之间来回切换)2:无需原子操作锁定及同步的开销.(如改一个 ...

  4. Python学习笔记--协程asyncio

    协程的主要功能是单线程并发运行 假设有3个耗时不一样的任务.看看协程的效果. 先来看没有使用协程情况: #!/usr/bin/python3 # -*- coding:utf-8 -*- import ...

  5. [转载]Python 3.5 协程究竟是个啥

    http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...

  6. [译] Python 3.5 协程究竟是个啥

    转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...

  7. Python基础之协程

    阅读目录 一 引子 二 协程介绍 三 Greenlet模块 四 Gevent模块 引子 之前我们学习了线程.进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道 ...

  8. python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

    yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...

  9. python基础(35):协程

    1. 前言 之前我们学习了线程.进程的概念,了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位.按道理来说我们已经算是把cpu的利用率提高很多了.但是我们知道无论是创建多进程还是创 ...

随机推荐

  1. js 点击不同li 切换颜色

    html <div> <li " onclick='addColor(this.id)'> 会议简介 </li> <li " onclic ...

  2. MyEclipse使用教程:添加和更新插件(二)

    [MyEclipse CI 2019.4.0安装包下载] 通过Eclipse Marketplace目录或各种更新站点类型添加插件来自定义您的Genuitec IDE. Genuitec提供以下IDE ...

  3. Hibernate 缓存机制详细分析

    在本篇随笔里将会分析一下hibernate的缓存机制,包括一级缓存(session级别).二级缓存(sessionFactory级别)以及查询缓存,当然还要讨论下我们的N+1的问题. 随笔虽长,但我相 ...

  4. C# Winform程序之间如何传递和接收参数 Process

    Program: static class Program    { /// <summary>         /// 应用程序的主入口点.         /// </summa ...

  5. CF1101D GCD Counting 点分治+质因数分解

    题意:求最长的树上路径点值的 $gcd$ 不为 $1$ 的长度. 由于只要求 $gcd$ 不为一,所以只要 $gcd$ 是一个大于等于 $2$ 的质数的倍数就可以了. 而我们发现 $2\times 1 ...

  6. CF1155 E.Guess the Root

    题目链接:Click here 题目大意:现在有一个至多11项的多项式\(F(x)\),你可以询问至多50个\(x\),黑盒子会告诉你\(F(x)\)的值,你现在要找到一个\(x\)使得\(F(x)= ...

  7. 利用gephi作人物网络图

    一.先利用word2vec训练数据得到模型 a.利用jieba对文本进行分词,并只提取词性为人名的词,去除分词长度为1和大于4的词 b.利用word2vec训练分词后的文本,并存储 c.利用训练后的模 ...

  8. 【转】【Linux经验】Codeblocks 13.12自动补全 、缩进解决

    最近使用Xubuntu 14.04学习C语言编程,发现了Codeblocks这款比较方便简单.适合我这种新手的IDE.之前用过Codeblocks10.04,它的代码自动补全和自动缩进让我眼前一亮.但 ...

  9. Jmeter获取未来时间

    1.添加前置处理器:BeanShell PreProcessor import java.text.SimpleDateFormat; import java.util.Calendar; impor ...

  10. HBase2.0新特性解析

    作者 | 个推大数据运维工程师 行者 升级背景 个推作为专业的数据智能服务商,在业务开展过程中存在海量的数据存储与查询的需求,为此个推选用了高可靠.高性能.面向列.可伸缩的分布式数据存储系统--HBa ...