【多线程相关其一】Python并发编程

news2024/9/26 1:17:30

1.为什么要引入并发编程

场景1:一个网络爬虫,按顺序爬取花了1个小时,采用并发下载减少到20分钟。
场景2:一个APP应用,优化前每次打开页面需要3秒,采用异步并发提升到每次200毫秒

引入并发,就是为了提升程序运行速度

1.1 程序提速的方法

在这里插入图片描述
单线程串行
一般程序运行时单线程串行,我们有一个线程,CPU先执行,然后进行IO(数据的读取和写出)
在IO期间,CPU是不做什么事情的。等IO完成后,CPU开始进行运算,然后进行下次IO.

整体时间是会有些浪费,那就是在IO期间,CPU是等待的状态。

引入多线程并发
当我们引入多线程并发时,它的运行就发生了变化。
CPU开始执行时,如果遇到了IO操作,它就会切换到另外一个task进行执行。
当IO完成了以后,会通知CPU进行下一步的处理。
这里有个知识点,咱们电脑中的CPU和IO,这两个它们是可以同时并行进行的。

IO的执行,比如说读取内存、磁盘、网络,它的过程是不需要CPU参与的
这样的话,CPU可以释放出来,来执行其他的TASK,实现并发的加速.
但这种原理上,其实还是一个CPU来进行运行的。

2、python对并发编程的支持

多线程:threading,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成
多进程:multiprocessing,利用多核CPU的能力,真正的并发执行任务
异步IO:asyncio,在单线程利用CPU和IO同时执行的原理,实现函数异步执行

python提供的额外函数来提供辅助能力

1.使用lock对共享资源加锁,防止冲突访问。
比如说,多线程和进程同时访问同一个文件,同时写入就会有冲突。可以把文件锁起来,就可以有序访问
2.使用Queue实现不同线程/进程之间的数据通信,实现生产者-消费者模式
比如说爬虫的时候,可以用生产者-消费者模式来改造,生产者就是边爬取,消费者就是边解析,这两个是分开的两个步骤
3.使用线程池Pool/进程池Pool,简化线程/进程的任务提交、等待结束、获取结果
4.使用subprocess启动外部程序的进程,并进行输入输出交互
比如说当你写好了一个exe程序,使用它,就可以调起这个exe程序,并跟它进行输入输出的交互,来实现交互式的进程通信

3、怎么选择多进程多线程协程

python并发编程的方式
多线程Thread、多进程Process、协程Coroutine
在这里插入图片描述
3.1、CPU密集计算与IO密集型计算
CPU密集型(CPU-bound):
CPU密集型也叫计算密集型,是指I/O在很短的时间就可以完成,CPU需要大量的计算和处理,特点是CPU占用率相当高。
(也就是说系统的硬盘、内存性能相对CPU要好很多。系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O(硬盘/内存),
I/O在很短的时间就可以完成,而CPU还有许多运算要处理,CPU Loading(负载)很高。)
例如:压缩解压缩、加密解密、正则表达式搜索

CPU使用率较高(例如:计算圆周率、对视频进行高清解码、矩阵运算等情况)的情况下,通常,线程数只需要设置为CPU核心数的线程个数就可以了。
(此时是最大效率。但是如果线程数/进程数远远超出 CPU 核心数量,反而会使得任务效率下降,因为频繁的切换线程或进程也是要消耗时间的。
因此对于 CPU 密集型的任务来说,线程数/进程数等于 CPU 数是最好的了。)
这一情况多出现在一些业务复杂的计算和逻辑处理过程中。比如说,现在的一些机器学习和深度学习的模型训练和推理任务,包含了大量的矩阵运算。

IO密集型(I/O bound)
IO密集型指的是系统运作大部分的状况是CPU在等I/O(硬盘/内存)的读/写操作,CPU占用率较低。
(硬盘适合长期保存大量的数据,而内存则适合暂存正在运行的程序和数据。)
例如:文件处理程序、网络爬虫程序、读写数据库程序

CPU 使用率较低,程序中会存在大量的 I/O 操作占用时间,导致线程空余时间很多,通常就需要开CPU核心数数倍的线程。
其计算公式为:IO密集型核心线程数 = CPU核数 / (1-阻塞系数)。
当线程进行 I/O 操作 CPU 空闲时,启用其他线程继续使用 CPU,以提高 CPU 的使用率。例如:数据库交互,文件上传下载,网络传输等。

简而言之,如果你的程序依赖大量的外部数据源,比如说内存、磁盘和网络,就是IO密集型
否则,如果只在CPU中进行计算,那就是CPU密集型。
详见:一分钟明白IO密集型与CPU密集型的区别

3.2、多进程、多线程、协程的对比

多进程Process(multiprocessing)多线程Thread(threading)多协程Coroutine(asyncio)
优点可以利用多核CPU并行运算相比进程,更轻量级、占用资源少内存开销最少、启动协程数量最多
缺点占用资源最多、可启动数目比线程少多线程只能并发执行,不能利用多CPU(GIL,GIL全局解释器锁,cpython特有的)支持的库有限制(aiohttp vs requests)、代码实现复杂
适用场景CPU密集型计算IO密集型计算、同时运行的任务数目要求不多IO密集型计算、需要超多任务运行、但有现成库支持的场景

3.3 .单线程与多线程爬虫

import threading
import time
 
from wj_demo.threading_demo.demo_base02.blog_spider import urls, craw
 
"""
I/O密集型操作
"""
 
 
def single_thread():
    """
    单线程爬取
    :return:
    """
    print("single_thread begin")
    for url in urls:
        craw(url)
    print("single_thread end")
 
 
def multi_thread():
    """
    多线程爬取
    :return:
    """
    print("multi_thread begin")
    threads = []
    for url in urls:
        threads.append(
            threading.Thread(target=craw, args=(url,))
        )
 
    for thread in threads:
        thread.start()
 
    for thread in threads:
        thread.join()
 
    print("multi_thread end")
 
 
if __name__ == "__main__":
    start = time.time()
    single_thread()
    end = time.time()
    single_thread_cost = end - start
    print(f"{single_thread.__name__} cost:", single_thread_cost, "seconds")
 
    start = time.time()
    multi_thread()
    end = time.time()
    multi_thread_cost = end - start
    print(f"{multi_thread.__name__} cost:", multi_thread_cost, "seconds")
 
    rate = single_thread_cost / multi_thread_cost
    print(f'{single_thread.__name__} is  cost {rate} {multi_thread.__name__}')
 
# single_thread cost: 17.854352235794067 seconds
# multi_thread cost: 6.92170524597168 seconds
# single_thread is  cost 2.579473063546734 multi_thread

3.4 异步协程asyncio爬虫

import asyncio
import time
 
from wj_demo.threading_demo.thread02_base02.blog_spider import urls  
 
start = time.time()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
tasks = [loop.create_task(async_craw(url)) for url in urls]
loop.run_until_complete(asyncio.gather(*tasks))
end = time.time()
print('use time seconds:', end - start)  
# use time seconds: 2.738969087600708

4、GIL全局解释器锁(英语:Global Interpreter Lock,缩写GIL)

是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。
即使在多核处理器上,使用GIL的解释器也只允许同一时间执行一个线程。

python解释器有多个版本 Cpython 、Jpython、Pypypython,但普遍使用的是Cpython解释器

GIL不是python的特点而是Cpython解释器的特点
GIL是保证解释器级别的数据的安全
GIL会导致同一个进程下的多个线程无法同时执行

在这里插入图片描述
为什么用GIL?

设计之初,是为了规避并发问题引入GIL,现在却很难去除了。
为了解决多线程之间数据完整性和状态同步问题

原因详解:

Python中对象的管理,是使用引用计数进行的,引用数为0则释放对象

开始:线程A和线程B都引用了对象obj,obj.ref_num=2,线程A和线程B都想撤销对obj的引用
在这里插入图片描述

简化了python对共享资源的管理
不加锁,会导致引用计数器混乱 释放掉别人的内存

怎么规避GIL带来的限制?

1、多线程threading机制依然是有用的,用于IO密集型计算
因为I/O(read,write,send,recv,etc)期间,线程会释放GIL,实现CPU和IO的并行
因为多线程用于IO密集型计算依然可以大幅提升速度
但是多线程用于CPU密集型计算时,只会更加拖慢速度

2、使用multiprocessing的多进程机制实现并行计算、利用多核CPU优势
为了应对GIL的问题,Python提供了multiprocessing

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1151615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos系统安装阿里云盘+简单使用

GitHub地址: 1、安装阿里云盘 wget https://github.com/tickstep/aliyunpan/releases/download/v0.2.7/aliyunpan-v0.2.7-linux-amd64.zip unzip aliyunpan-v0.2.7-linux-amd64.zip mv aliyunpan-v0.2.7-linux-amd64 /usr/local/aliyunpan ln -s /usr/local/aliyu…

安装Jdk 报错 ,Java SE Development Kit 8 Update 202(64-bit)安装完毕之前,向导被中断

具体原因没有找到,估计是由于jdk 没有删干净导致的,我的处理方法是,将 Java的注册表全然后手动安装 Jdk和导入注册表(在同事那里获取jdk文件 压缩包,并将 java的注册表导出,放在自己电脑上使用。&#xff0…

动手学深度学习——第七次学

LeNet(LeNet-5)由两个部分组成: 卷积编码器和全连接层密集块 卷积把高宽不断变小,把通道数逐渐增多,(最后高宽会变成,通道会变得很大,然后做全连接进行输出)通道信息可以…

Leetcode—1488.避免洪水泛滥【中等】

2023每日刷题&#xff08;十四&#xff09; Leetcode—1488.避免洪水泛滥 算法思想 将晴天的日期全部记录在set<int> sun中使用unordered_map<int, int> lakeRainy来记录每个湖泊上一次下雨的日期遇到晴天时先不用管抽哪个湖当下雨时&#xff0c;湖泊已经装满水时…

QT5 通过 webview2 加载网页

官方文档参考&#xff1a;https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/get-started/win32 Webview2依赖的头文件和库 头文件主要为&#xff1a;WebView2和WixLibrary&#xff0c;存储在include/external 库主要为&#xff1a;WebView2LoaderStatic.lib和W…

C++——类和对象(构造函数与析构函数)

构造函数与析构函数 本章思维导图&#xff1a; 注&#xff1a;本章思维导图对应的Xmind文件和.png文件都已导入到”资料“中 1. 构造函数 以前&#xff0c;我们写一个Date类一般是这么写的&#xff1a; class Date { public :void Init(int year, int month, int day){_year…

Unity Animator cpu性能测试

测试案例&#xff1a; 场景中共有4000个物体&#xff0c;挂在40个animtor 上&#xff0c;每个Animator控制100个物体的动画。 使用工具&#xff1a; Unity Profiler. Unity 版本&#xff1a; unity 2019.4.40f1 测试环境&#xff1a; 手机 测试过程&#xff1a; 没有挂…

解读电力系统中的GPS北斗卫星同步时钟系统

随着电力系统的快速发展,变电站中的各类系统 &#xff1a;计算机监控系统、水情测报系统、视频监控系统 状态监测系统 生产信息管理系统等&#xff0c;各类装置&#xff1a;继电保护装置、故障录波装置、PMU装置、事件顺序记录SOE功能越来越强大&#xff0c;需要采集、记录的数…

CSS3背景样式

在CSS 2.1中&#xff0c;background属性的功能还无法满足设计的需求&#xff0c;为了方便设计师更灵活地设计需要的网页效果&#xff0c;CSS3在原有background基础上新增了一些功能属性&#xff0c;可以在同一个对象内叠加多个背景图像&#xff0c;可以改变背景图像的大小尺寸&…

LeetCode热题100 48.旋转图像

题目描述 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9…

2022年09月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 运行以下代码&#xff0c;结果输出的是&#xff1f;&#xff08; &#xff09; means[Thank,You] print(len(means))A…

Android开发知识学习——TCP / IP 协议族

文章目录 学习资源来自&#xff1a;扔物线TCP / IP 协议族TCP连接TCP 连接的建立与关闭TCP 连接的建立为什么要三次握手&#xff1f; TCP 连接的关闭为什么要四次挥手&#xff1f; 为什么要⻓连接&#xff1f; 常见面试题课后题 学习资源来自&#xff1a;扔物线 TCP / IP 协议…

潜力无限!深眸科技以工业视觉软硬件一体化解决方案深入应用场景

工业视觉作为智能制造的眼睛&#xff0c;在制造业各场景中具有广泛的应用前景&#xff0c;尤其是在检测、引导、定位、测量等方面应用需求不断提高。深眸科技为进一步巩固和加强技术领先优势&#xff0c;持续拓宽机器视觉技术的应用边界&#xff0c;通过先进的硬件设备和自研的…

86 最小栈

最小栈 题解1 STL大法好题解2 辅助最小栈&#xff08;直观&#xff0c;空间换时间&#xff09;题解3 不需要额外空间(!!!差值!!!) 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初…

支持「导入/导出」,应用迁移瞬间完成_三叠云

应用导入/导出 路径 应用管理 >> 创建新应用 功能简介 1. 应用程序支持「导出」功能&#xff0c;即将应用独立封装导出&#xff0c;用于三叠云系统内应用导入。 2. 应用程序支持「导入」功能&#xff0c;可以帮助用户将数据或文件导出到其他设备或应用程序中&#x…

思维导图在学习中的应用

思维导图在做学习中发挥着非常高效的作用&#xff0c;因为因为思维导图只有一页&#xff0c;所以需要准备和组织内容的时间会大大减少。并且思维导图的可视化的结构&#xff0c;可以让你瞬间将所有信息一览无余。而传统的笔记方法&#xff0c;会记录好几页。不仅信息冗杂&#…

【经典面试】87 字符串解码

字符串解码 题解1 递归(程序栈)——形式语言自动机(LL(1)) : O(S)另一种递归(直观) 题解2 2个栈(逆波兰式)1个栈(参考官方&#xff0c;但是不喜欢) 给定一个经过编码的字符串&#xff0c;返回它解码后的字符串。 编码规则为: k[encoded_string]&#xff0c;表示其中方括号内部的…

Linux 权限管理(二)

文件类型和访问权限&#xff08;事物属性&#xff09; linux前都会有一串这个字符&#xff0c;第二字符到第九字符分别表示拥有者&#xff0c;所属组&#xff0c;和other所对应的权限。那么第一个字符表示什么呢&#xff1f; 第一个字符表示文件类型&#xff1a; d&#xff1a…

开放式耳机百元价位推荐哪款比较好一点、最值得入手的开放式耳机

不知道有没有和我一样的朋友&#xff0c;在工作的时候喜欢带着耳机&#xff0c;享受音乐带来的愉悦。然而&#xff0c;传统的入耳式耳机在长时间佩戴时会给耳朵带来不适感&#xff0c;甚至损害听力。 因此我现在会使用开放式耳机&#xff0c;采用了开放式设计&#xff0c;不需…

流程封装与基于加密接口的测试用例设计

接口测试仅仅掌握 Requests 或者其他一些功能强大的库的用法&#xff0c;是远远不够的&#xff0c;还需要具备能根据公司的业务流程以及需求去定制化一个接口自动化测试框架的能力。所以&#xff0c;接下来&#xff0c;我们主要介绍下接口测试用例分析以及通用的流程封装是如何…