Python中的协程、线程和进程
一.协程与多线程和多进程一起使用有什么不同
协程、多线程和多进程都是实现程序并发执行的方法,不过它们在工作方式和适合的应用场景上存在一些区别。
1.协程(Coroutine)
协程是在单一线程内部实现并发的,由于只涉及单一线程,不存在多线程中常见的数据竞争等线程同步问题。当协程遇到 IO 操作(如文件读写、网络请求)时,它会将控制权让给其他协程,直到 IO 操作完成。因此,协程适合用于 IO 密集型任务。
2.多线程(Multithreading)
多线程通过在单个进程中同时运行多个线程来实现并发。每个线程可以独立执行并拥有自己的调用堆栈,但线程之间可以共享进程的内存空间,从而方便地共享状态。需要注意的是,由于存在数据共享,数据同步(如通过锁)会是多线程编程的一个常见问题。多线程适合用于既有计算密集型任务,又有 IO 密集型任务的场景。
3.多进程(Multiprocessing)
多进程通过并行运行多个进程来实现,并且每个进程有自己独立的内存空间。进程间的通信(IPC)通常通过使用管道、套接字等完成,这比线程间的状态共享更复杂。由于多进程不共享内存,它在需求中有严格的隔离性或是利用多核并行计算时是个好选择。
需要注意在 Python 中,由于全局解释器锁(GIL)的存在,即使是在多核 CPU 环境下,Python 的多线程在执行 CPU 密集型任务时性能得不到明显提升,反而多进程可以更好利用多核 CPU。所以对于 Python 来说,协程是最适合 IO 密集型任务,而对于 CPU 密集型任务可以选择多进程。
二.在 Python 中如何实现多线程和多进程
在 Python 中实现多线程和多进程可以使用 Python 标准库中的 threading 和 multiprocessing 模块。
1.在 Python 中创建和使用多线程的一个基本示例
import threading
def print_numbers():
for i in range(10):
print(i)
def print_letters():
for letter in 'abcdefghijklmnopqrstuvwxyz':
print(letter)
# 创建线程
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)
# 启动线程
thread1.start()
thread2.start()
# 等待线程执行完成
thread1.join()
thread2.join()
在上面的代码中,我们定义了两个函数 print_numbers 和 print_letters,然后以这两个函数作为目标创建了两个线程。start 方法用于启动线程,join 方法用于等待线程执行完成。
2.在 Python 中创建和使用多进程的一个基本示例
import multiprocessing
def print_numbers():
for i in range(10):
print(i)
def print_letters():
for letter in 'abcdefghijklmnopqrstuvwxyz':
print(letter)
# 创建进程
process1 = multiprocessing.Process(target=print_numbers)
process2 = multiprocessing.Process(target=print_letters)
# 启动进程
process1.start()
process2.start()
# 等待进程执行完成
process1.join()
process2.join()
在上面的代码中,我们创建和使用多进程的方式与多线程基本一致,只是将 threading.Thread 换成了 multiprocessing.Process。
三.Python 中的多线程间通讯方式,多进程间间通讯方式分别有哪些
使用这些方式时需要保证进程间通信和线程同步的安全性,防止出现数据竞争、死锁等问题。
1.Python 中多线程间通讯方式
由于线程共享进程的内存空间,可以直接访问共享变量进行通信。但需要注意的是,必须保证操作的原子性,避免在多线程环境下产生数据竞争。Python 中常用来保证多线程安全的工具包含:
锁:包括互斥锁(Lock),可重入锁(RLock),条件变量(Condition),信号量(Semaphore)等; 队列: queue模块提供了同步队列(Queue)、LIFO 队列(LifoQueue)以及优先级队列(PriorityQueue),这些队列都是线程安全的,可以在不同线程之间交换数据,非常方便。
2.Python 中多进程间通讯方式
因为进程拥有各自的内存空间,不能直接共享变量,通常可以通过以下方式进行通信:
管道(Pipe): multiprocessing模块中的Pipe()函数可以返回一个管道的两个端点,可以分别发放给两个进程,让它们通过管道的方式进行通信;队列(Queue): multiprocessing模块提供的Queue类是一个具有先进先出特性的队列,也是进程安全的,方便多个进程之间的数据交换;共享内存: multiprocessing模块中的Value或Array,能在多个进程间共享;服务器进程:一个由 Manager()函数返回的管理器对象控制的服务器进程,这个进程包含的 python 对象,可以被其他进程通过代理进行访问。如果有大量的共享数据,这种方式可能会比更底层的共享方式更合适。
四.nest_asyncio 库
解决 Python 的原生 asyncio 库不允许在同一个线程中运行多个事件循环的问题,即 RuntimeError: This event loop is already running。如下所示:
import nest_asyncio
nest_asyncio.apply()
async def main():
await asyncio.sleep(1)
print('Hello, World!')
asyncio.run(main())
这个例子即使在运行一个事件循环的环境中(如 Jupyter notebook),这段代码也可以正常运行。这是因为 nest_asyncio.apply() 允许在同一线程中运行多个事件循环。
参考文献
[1] asyncio(异步 I/O):https://docs.python.org/zh-cn/3/library/asyncio.html
[2] https://github.com/erdewit/nest_asyncio
[3] https://docs.python.org/3/library/threading.html
[4] https://docs.python.org/3/library/multiprocessing.html
NLP工程化
1.本公众号以对话系统为中心,专注于Python/C++/CUDA、ML/DL/RL和NLP/KG/DS/LLM领域的技术分享。
2.本公众号Roadmap可查看飞书文档:https://z0yrmerhgi8.feishu.cn/wiki/Zpewwe2T2iCQfwkSyMOcgwdInhf

NLP工程化

飞书文档

Python中的协程、线程和进程的更多相关文章
- python中的协程及实现
1.协程的概念: 协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈. 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来的时候,恢复先前保存的寄存器上下文和栈. 因此,协程能保留 ...
- python中的协程:greenlet和gevent
python中的协程:greenlet和gevent 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. 1.通过yield实现协程: 代码: import time def A(): ...
- Python中异步协程的使用方法介绍
1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...
- Python中Paramiko协程方式详解
什么是协程 协程我们可以看做是一种用户空间的线程. 操作系统对齐存在一无所知,需要用户自己去调度. 比如说进程,线程操作系统都是知道它们存在的.协程的话是用户空间的线程,操作系统是不知道的. 为什么要 ...
- 协程及Python中的协程
1 协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(其实并没有说明白~) 我觉得单说协程,比较抽象,如果对线程有一定了解 ...
- python中多进程+协程的使用以及为什么要用它
前面讲了为什么python里推荐用多进程而不是多线程,但是多进程也有其自己的限制:相比线程更加笨重.切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL, ...
- Python | 详解Python中的协程,为什么说它的底层是生成器?
今天是Python专题的第26篇文章,我们来聊聊Python当中的协程. 我们曾经在golang关于goroutine的文章当中简单介绍过协程的概念,我们再来简单review一下.协程又称为是微线程, ...
- Python中的协程,为什么说它的底层是生成器?
我们曾经在golang关于goroutine的文章当中简单介绍过 协程 的概念,我们再来简单review一下.协程又称为是微线程,英文名是Coroutine.它和线程一样可以调度,但是不同的是线程的启 ...
- python中的协程
目录 协程是啥 协程和线程差异 简单实现协程 greenlet 安装方式 gevent 安装 1. gevent的使用 2. gevent切换执行 3. 给程序打补丁 进程.线程.协程对比 请仔细理解 ...
- python中的协程并发
python asyncio 网络模型有很多中,为了实现高并发也有很多方案,多线程,多进程.无论多线程和多进程,IO的调度更多取决于系统,而协程的方式,调度来自用户,用户可以在函数中yield一个状态 ...
随机推荐
- 吴恩达人工智能-python实现逻辑回归
吴恩达人工智能 逻辑回归python代码实现 逐行注释 import numpy as np import pandas as pd from matplotlib import pyplot as ...
- Django框架——路由控制、视图层
文章目录 1 路由控制 一 Django中路由的作用 二 简单的路由配置 三 有名分组 四 路由分发 五 反向解析 六 名称空间 七 django2.0版的path 基本示例 path转化器 注册自定 ...
- 素数是个什么东西 prime number
/** * ********************************************************************* * 只有1和它本身两个正因数的自然数,叫质数 ...
- Mysql数据库、表设计规范指南
结合网上资料与项目实际情况,总结下列MYSQL数据库设计规范. 一.MYSQL数据库设计规范1.数据库命名规范采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线'_'组成,禁止使 ...
- Centos7下创建centos-home逻辑分区
1备份要挂载的文件夹 查看home文件夹有无文件,如有文件一定要记得备份 2创建逻辑分区 2.1查看已有逻辑分区 2.2查看磁盘分区情况 2.3查看磁盘PV 2.4创建逻辑分区 lvcreate -n ...
- 运行 Python 脚本/代码的几种方式
哈喽大家好,我是咸鱼 我们知道,python 脚本或者说 python 程序其实是一个包含了 python 代码的文件.要让它们实现特定功能,我们需要知道该如何运行(run)它 通过运行 python ...
- Go 如何实现多态
在 Go 语言中,虽然没有经典的面向对象编程中的继承和多态的概念,但你可以通过接口(interface)来实现多态性.Go 语言鼓励组合和接口多态,这使得代码更加灵活和模块化.下面将详细介绍 Go 语 ...
- CSP-2023 初赛游记
9.16 上午 今天就不早读了. 去前做了个 2019 的题,60 多分,感觉挺危. 去比赛前 30min 发现没带身份证,去宿舍拿的. 前 10min 发现没有笔,借了一些,但是发现还有一个小时才开 ...
- ThreadPoolExecutor使用浅谈
1. 基础介绍 ThreadPoolExecutor是Python标准库concurrent.futures模块中的一个类,用于实现线程池的功能. ThreadPoolExecutor模块相比于thr ...
- DNS 服务 docker-bind 的部署使用
前言 前面使用 nginx 代理转发了几个域名到服务器,但是每次添加一个域名都需要在客户端添加一行 hosts 文件,无疑是繁琐的,其中也提到可以使用 DNS 来实现自动解析域名 到指定服务器的功能, ...