python5:基于多进程的并发编程、基于协程的并发编程的学习笔记

进程

  • 为什么要使用多进程?——GIL的存在,多线程实际不是并发执行
    将任务分为两类:
  • IO密集型(多线程)
  • CPU密集型(多进程)

多进程的基本用法

concurrent.futures.process.ProcessPoolExecutor#进程池 (与线程池用法一致
multiprocessing.Pool#单个进程
multiprocessing.Pool #进程池

可直接学习复习该链接:https://blog.csdn.net/ifhuke/article/details/128642625
有进程间通信,进程池
在这里插入图片描述

创建进程

委托操作系统创建,但不同操作系统创建进程的方式不一样

  • linux:fork:从父进程中继承内存(从运行了一半的程序中裂变出去)
  • windows:spawn:重新运行Python程序(1. 启动python程序; 2.import代码文件
  • 在这里插入图片描述
  • 在这里插入图片描述

协程

一种用户态的上下文切换技术(通过一个线程实现代码块间的相互切换执行,在一个协程中,遇到io等待时间,可以利用这个等待时间去做其他事情
yield就是一个协程思想的实现

yield、yield from

yield可以将函数变成生成器
在函数中加yield关键字,调用它,就会返回一个生成器
在这里插入图片描述
生成器的目的不是为了将代码打包,目的是为了生产或者返回一些值
1 创造生成器
2 通过next获取下一个值(可以理解为next去取yield的值)
3 如果遇到了StopIteration,说明内容生成结束
以上的用法,也叫做迭代器协议,就是不断从中去取内容,可以被for去使用
在这里插入图片描述
通过yield可以改变程序执行顺序,因此协程也称之为“用户态的线程”或“微线程”,即程序执行顺序是受用户控制的。
在Python中,协程是基于单线程的。
Tornado是一个Web开发框架,内部使用协程提供高并发

在这里插入图片描述
通过主线程去调度,即从g2中获得i,给到g3,再得到值,改进这个情况,引入yield from
在这里插入图片描述

yield是将生成器作为结果返回,yield from是把生成器的结果作为结果返回。但后来不用这个写法了,就先pass

协程的相关概念

  • 协程函数:定义为async def的函数
  • 协程对象:调用协程函数返回的对象
  • 事件循环:event loop 并发执行任务的大脑,判断哪些任务已处于可执行状态,并执行(循环只是主线程不断从事件队列里面取值/函数的过程)
  • 协程任务:rask 事件循环调度的最小单位,可由协程对象转化

关键字概述

  • async 定义函数时加上async,则该函数为协程函数
  • await 后面是一个可等待对象,如协程对象,协程任务---->去运行这个函数,运行完再继续fanhui
  • asyncio编写并发代码的库
  • run运行最高层级的入口点
  • asyncio.create_task() 创建task对象
import asyncio
import time
async def async_test(delay:int,content):
    await asyncio.sleep(delay)
    print(content)

async def main():
    task_lady = asyncio.create_task(async_test(1,"lady"))#创建task
    task_killer = asyncio.create_task(async_test(2,"killer9"))
    await task_killer#可以await所有任务,如果只await了耗时短的,那么其他任务没有完成就结束了

if __name__ == '__main__':
    print(f"start at {time.strftime('%X')}")
    asyncio.run(main())
    print(f"end at {time.strftime('%X')}")

  • gather 接收列表,结果是一个由所有返回值聚合而成的列表。结果值得顺序与was

生成器如何使用协程

借助工具实现协程,在这些工具中,使用yield关键字

  • Tornado提供了各种协程版的函数
  • 使用gevent的猴子补丁,可以不使用协程的写法,但是有协程的开发效果

asyncio模块

用来编写并发代码的酷,被用作多个提供高性能Python异步框架的基础,包括网络和网站服务,数据库链接库,分布式任务队列等,asyncio往往是构建IO密集型和高层级 结构化 网络代码的最佳选择

import time
import asyncio

async def f1():
	time.sleep(1)#这是线程阻塞的代码  整个线程会停住一秒
	print("f1:done")

async def f2():
	time.sleep(1)#这是线程阻塞的代码
	print("f2:done")

async def main():
	await f1();
	await f2();

if __name__ == "__main__":
	time = time.time();
	asyncio.run(main());#入口
	time2 = time.time();
	print(f"耗时{time2-time:.2f} ");

耗时2s

用asyncio后改变的代码:

import time
import asyncio

async def f1():
	await asyncio.sleep(1)#这是非阻塞的协程 ,类似于yeild
	print("f1:done")

async def f2():
	asyncio.sleep(1)#非阻塞的协程 ,类似于yeild
	print("f2:done")

async def main():
	await f1();#等待协程结束
	await f2();

依然2s,依旧不是并行运行的,需要用到
在这里插入图片描述
修改代码:

async def main():
	await asyncio.gather(f1(),f2());

修改后,耗时1s,是并发操作
所以在异步编程中,如果有一处代码写成了同步,则整个代码都同步。
所以,像锁,sleep,迭代,队列,网络请求(socket)等都需要用异步资源
注意很多的第三方模块都是同步的,所以我们需要确定是“异步”的第三方库 https://github.com/aio-libs

async 和 await

创建协程的方式有两种,一种是yield关键字,一种是async关键字,我们一般用后者
定义函数时,加上async修饰,即async def func(),则该函数为协程函数,协程函数返回的对象即为协程对象

await后面是一个可等待对象,如协程对象,协程任务,用于告诉eventloop在此协程中需要等待后面的函数运行完成后才能继续(即执行下一个协程),运行完成后返回结果

新的协程如何运行
  • 在其他协程中被await
  • 使用asyncio模块提供第一个协程的运行
async def f_3():
	print("f3 doing")
	await f_4()#等f4

async def f_4():
	print("f4 doing")

if __name__=="__main__":
	asyncio.run(f_3())#第一个协程的运行

或者使用task方法执行协程

在这里插入图片描述

并发方案的选择

1 分布式,还是单击

  • 分布式,只能选择多进程

2 CPU密集,还是IO密集

  • CPU密集,多进程

3 单击IO密集型,并发数多不多

  • 如果不多,多线程(推荐)
  • 如果多,协程
  • 如果特别多:多进程+多线程+协程

4 是否有动态调度

  • 没有, 线程池
  • 有,手动创建线程

并发任务之间的通信:队列
并发任务之间的同步:锁

相关推荐

  1. python并发编程-进程、线2

    2024-03-22 22:00:02       14 阅读
  2. Python编程异步爬虫——基本原理

    2024-03-22 22:00:02       18 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-22 22:00:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-22 22:00:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-22 22:00:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-22 22:00:02       20 阅读

热门阅读

  1. SQL Server创建存储过程

    2024-03-22 22:00:02       19 阅读
  2. 力扣-283. 移动零

    2024-03-22 22:00:02       20 阅读
  3. 基于STM32的寻迹小车设计详细论文

    2024-03-22 22:00:02       15 阅读
  4. Thingworx高可用集群部署(七)-Zookeeper集群部署

    2024-03-22 22:00:02       16 阅读
  5. Redis切换数据库的详细介绍

    2024-03-22 22:00:02       23 阅读
  6. 洛克王国卡小游戏2

    2024-03-22 22:00:02       16 阅读
  7. Yarn 管理的前端项目转换为使用 npm

    2024-03-22 22:00:02       20 阅读
  8. Redis 产生阻塞的原因,如何找到阻塞的原因

    2024-03-22 22:00:02       16 阅读
  9. 快速排序--C语言

    2024-03-22 22:00:02       21 阅读
  10. 【大数据技术】Hive基本原理以及使用教程

    2024-03-22 22:00:02       19 阅读
  11. docker 修改默认存储位置

    2024-03-22 22:00:02       17 阅读
  12. CSS color-mix() 函数

    2024-03-22 22:00:02       20 阅读
  13. less与sass哪个更好用

    2024-03-22 22:00:02       21 阅读
  14. NoSQL

    NoSQL

    2024-03-22 22:00:02      16 阅读
  15. python基础知识(四)

    2024-03-22 22:00:02       19 阅读