Python中的协程、线程和进程

news/2024/7/5 10:45:49

一.协程与多线程和多进程一起使用有什么不同

  协程、多线程和多进程都是实现程序并发执行的方法,不过它们在工作方式和适合的应用场景上存在一些区别。

1.协程(Coroutine)

  协程是在单一线程内部实现并发的,由于只涉及单一线程,不存在多线程中常见的数据竞争等线程同步问题。当协程遇到 IO 操作(如文件读写、网络请求)时,它会将控制权让给其他协程,直到 IO 操作完成。因此,协程适合用于 IO 密集型任务。

2.多线程Multithreading

  多线程通过在单个进程中同时运行多个线程来实现并发。每个线程可以独立执行并拥有自己的调用堆栈,但线程之间可以共享进程的内存空间,从而方便地共享状态。需要注意的是,由于存在数据共享,数据同步(如通过锁)会是多线程编程的一个常见问题。多线程适合用于既有计算密集型任务,又有 IO 密集型任务的场景。

3.多进程(Multiprocessing)

  多进程通过并行运行多个进程来实现,并且每个进程有自己独立的内存空间。进程间的通信(IPC)通常通过使用管道、套接字等完成,这比线程间的状态共享更复杂。由于多进程不共享内存,它在需求中有严格的隔离性或是利用多核并行计算时是个好选择。

  需要注意在 Python 中,由于全局解释器锁(GIL)的存在,即使是在多核 CPU 环境下,Python 的多线程在执行 CPU 密集型任务时性能得不到明显提升,反而多进程可以更好利用多核 CPU。所以对于 Python 来说,协程是最适合 IO 密集型任务,而对于 CPU 密集型任务可以选择多进程。

二.在 Python 中如何实现多线程和多进程

  在 Python 中实现多线程和多进程可以使用 Python 标准库中的 threadingmultiprocessing 模块。

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_numbersprint_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 模块中的 ValueArray,能在多个进程间共享;
  • 服务器进程:一个由 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


http://lihuaxi.xjx100.cn/news/1931455.html

相关文章

Spring Boot 如何使用 Maven 实现多环境配置管理

Spring Boot 如何使用 Maven 实现多环境配置管理 实现多环境配置有以下几个重要原因: 适应不同的部署环境:在实际部署应用程序时,通常会有多个不同的部署环境,如开发环境、测试环境、生产环境等。每个环境可能需要不同的配置&…

【算法题】33. 搜索旋转排序数组

题目 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], nums[0], nums[…

20 太空漫游

效果演示 实现了一个太空漫游的动画效果&#xff0c;其中包括火箭、星星和月亮。当鼠标悬停在卡片上时&#xff0c;太阳和星星会变成黄色&#xff0c;火箭会变成飞机&#xff0c;月亮会变成小型的月亮。整个效果非常炫酷&#xff0c;可以让人想起科幻电影中的太空漫游。 Code &…

几个实用网站

论文短语&#xff1a;https://www.phrasebank.manchester.ac.uk/ 翻译&#xff1a;https://www.deepl.com/en/translator 润色&#xff1a;https://quillbot.com/ 榜单&#xff1a;www.paperwithcode.com ****NLP民工的乐园: 几乎最全的中文NLP资源库&#xff1a;****https…

基于STM32+QT设计的无人超市消费系统_139

基于STM32+QT设计的无人超市消费系统 一、前言 1.1 研究背景 随着科学技术的不断提高,计算机科学日渐成熟,其强大的功能已为人们深刻认识,它已进入人类社会的各个领域并发挥着越来越重要的作用。 超市形式在我国于20世纪90年代初期起步,现已成为我国零售业的一种重要形态…

【刷题日志】深度理解除(/)与取模(%)附水仙花数以及变种水仙花数题解

文章目录 &#x1f680;前言&#x1f680;除与取模&#x1f680;水仙花数&#x1f680;变种水仙花数 &#x1f680;前言 本专栏文章都直奔刷题主题&#xff0c;阿辉都不会在废话了&#xff0c;加油&#xff0c;少年&#xff01;&#xff01;&#xff01; &#x1f680;除与取…

开发辅助三(缓存Redisson分布式锁+分页插件)

缓存 缓存穿透&#xff1a;查询一个不存在的数据&#xff0c;由于缓存不命中&#xff0c;将大量查询数据库&#xff0c;但是数据库也没有此记录。 没有将这次查询的null写入缓存&#xff0c;导致了这个不存在的数据每次请求都要到存储层查询&#xff0c;失去了缓存的意义。 解…

虹科方案丨从困境到突破:TigoLeap方案引领数据采集与优化变革

来源&#xff1a;虹科工业智能互联 虹科方案丨从困境到突破&#xff1a;TigoLeap方案引领数据采集与优化变革 原文链接&#xff1a;https://mp.weixin.qq.com/s/H3pd5G8coBvyTwASNS_CFA 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 在数字化工厂和智能制造时…