python 并发汇总
一、多进程(Multiprocessing)
1、使用场景
适合CPU密集型任务,因为每个进程运行在独立的Python解释器中,不受全局解释器锁(GIL)的影响。
多个进程可以真正并行地执行,并利用多核处理器的能力。
2、代码
from multiprocessing import Process
import time
def task():
print("Task is running")
time.sleep(10)
processes = []
for _ in range(50):
p = Process(target=task)
processes.append(p)
p.start()
for p in processes:
p.join()
同时启动50个进程,50个进程执行同样的任务,他们没有GIL锁,时间几乎是并发的,执行结束10s左右
# time 统计的时间 real 0m10.135s user 0m0.094s sys 0m0.179s # 查看进程 ps -ef | grep -w 'process_example.py' | wc -l 52 root 3925498 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925499 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925500 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925501 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925502 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925503 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925504 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925505 3925455 0 15:52 pts/0 00:00:00 python3 process_example.py root 3925565 3885440 0 15:52 pts/1 00:00:00 grep --color=auto process_example.py
二、多线程(Threading)
1、使用场景
适用于I/O密集型任务,如文件读取、网络请求等。线程共享内存,因此适合需要频繁数据交换的任务。
相比之下,对于CPU密集型任务,由于几乎所有的时间都用于执行Python代码,GIL几乎始终被一个线程所占用,导致其他线程无法并行执行。
然而,在I/O密集型任务中,频繁的I/O操作和GIL的适时释放使线程能够更好地并行工作,从而减轻GIL对性能的负面影响。
因此,在I/O密集型应用场景中,多线程的使用通常能够有效地提高性能,因为阻塞I/O操作的等待时间可以被用来执行其他进程或线程的工作。
2、案例
import threading
import time
def cpu_intensive_task(n):
print(f"CPU Thread {n} starting...")
count = 0
for _ in range(50): # 重复执行多次耗时任务
# 一个更重的计算任务
for i in range(10**7):
count += i
time.sleep(1) # 增加一些休眠时间
print(f"CPU Thread {n} finished with count = {count}")
def io_intensive_task(n):
print(f"I/O Thread {n} starting...")
for _ in range(50):
# 模拟一个I/O耗时任务,例如文件读写
time.sleep(2) # 模拟I/O等待时间
print(f"I/O Thread {n} finished.")
threads = []
num_cpu_threads = 4
num_io_threads = 4
# 创建CPU密集型任务的线程
#for i in range(num_cpu_threads):
# t = threading.Thread(target=cpu_intensive_task, args=(i,))
# threads.append(t)
# t.start()
# 创建I/O密集型任务的线程
for i in range(num_io_threads):
t = threading.Thread(target=io_intensive_task, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("All threads have completed.")
3、进程池和线程池这里不再讨论
https://www.cnblogs.com/dgp-zjz/p/17536048.html
4、GIL 全局解释器锁(Global Interpreter Lock,简称 GIL)
GIL是一种用于保护 Python 解释器在多线程环境下的数据完整性的机制。GIL 只存在是 CPython 解释器中,即官方的 Python 解释器实现
GIL 是一个互斥锁,你可以使用多线程来并发处理任务,但在同一时刻只能有一个线程在执行 Python 字节码。
https://www.cnblogs.com/dgp-zjz/p/17535159.html
三、异步编程(asyncio)
1、使用场景
适合处理大量并发I/O操作,如网络应用、服务器编程等。使用单线程事件循环来调度任务。
asyncio本质上是基于协程的,其async和await语法就是为了实现这样的模式。
2、代码
import asyncio
async def task():
print("Task is running")
await asyncio.sleep(20) # 模拟I/O操作
async def main():
tasks = [task() for _ in range(50)]
await asyncio.gather(*tasks)
asyncio.run(main())
经过测试asyncio 模块没有出现GIL锁占用时间且是一个线程
GIL: 0.00%, Active: 0.00%, Threads: 1
四、携程(Coroutines)
1、使用场景
协程是Python中的异步设计模式,利用yield和await,用于非阻塞式的I/O操作
协程是单线程下的并发,它是程序员级别的,我们来控制如何切换。
进程的开销 >>>>>> 线程的开销 >>>>>> 协程的开销
协程的使用需要借助于第三方模块 gevent 模块或者 asyncio 模块
2、案例(这里介绍gevent的方式)
import gevent
from gevent import monkey
import time
# Patch all to make the standard library cooperative
monkey.patch_all()
def task(task_id):
print(f"Task {task_id} started.")
# 模拟一个耗时操作
time.sleep(1)
print(f"Task {task_id} completed.")
def main():
# 创建多个任务
tasks = [gevent.spawn(task, i) for i in range(5)]
# 并发地运行所有任务
gevent.joinall(tasks)
if __name__ == '__main__':
main()
补充说明
monkey.patch_all():
将标准库的一些阻塞操作打补丁,使其在 gevent 的绿色线程环境中变成非阻塞的。这包含对 time.sleep、socket 等模块的修改,使它们可以与 gevent 的事件循环协作。
猴子补丁它会将(socket、select、threading 等)这些模块的阻塞式 I/O 操作替换为非阻塞的版本
gevent.spawn(task, i):
gevent.spawn 用于启动新的 greenlet,这是 gevent 中的轻量级协程。每个任务会异步地运行而不阻塞其他任务。
gevent.joinall(tasks):
等待所有的 gevent 协程完成,可以理解为同步等待所有并发任务完成。
https://www.cnblogs.com/dgp-zjz/p/17535797.html
五、celery 分布式任务队列库
它主要用于处理实时请求与任务调度,而不是直接用于运行异步代码。celery 允许你在生产环境中分发一组任务,以便通过消息中间件(如 RabbitMQ 或 Redis)与不同的工作节点进行通信。
异步执行:celery 提供了一种优雅的方式将任务异步地推送到后台,不阻塞主线程。
横向扩展:可以通过增加更多的 worker 实例来扩展处理能力。
与 Web 框架的集成:伴随 Flask、Django 等框架,celery 也有根据框架定制的插件或使用指南。
celery 的应用场景
-
异步任务执行:
- 允许你将耗时长的任务放在后台运行,例如发送电子邮件、生成报告或处理图像。
-
定时任务:
- 使用集成的
celery beat执行定时任务,使其可以替代一些传统的 cron 作业。
- 使用集成的
-
任务工作流:
- 支持复杂的工作流,允许任务之间有依赖关系。
使用案例:异步秒杀
https://www.cnblogs.com/dgp-zjz/p/17773173.html
六、性能分析工具
1、py-spy
功能:用于对正在运行的Python程序进行采样分析(sampling profiler),可以实时监控CPU的使用情况。
2、用法
# pip install py-spy py-spy top --pid <PID>

2、memray
1、功能
memray是一款高效的内存分析工具,用于检测Python程序的内存使用情况及潜在的内存泄漏
2、用法
# pip install memray memray run script.py


浙公网安备 33010602011771号