Python的线程、进程与协程

文章目录

一、进程和线程的比较

线程和进程是并发执行的两种主要方式

1. 定义

  • 进程:进程是操作系统分配资源的基本单位,每个进程都有独立的内存空间,包含代码、数据和系统资源。进程之间相互隔离,一个进程崩溃不会影响其他进程。
  • 线程:线程是进程内的执行单元,一个进程可以包含多个线程。线程共享进程的内存空间和资源,因此线程间的通信比进程间更高效,但也更容易出现数据竞争等问题。

2. 内存空间

  • 进程:每个进程有独立的内存空间,进程间通信需要通过IPC(Inter-Process Communication)机制,如管道、消息队列、共享内存等。
  • 线程:线程共享进程的内存空间,线程间可以直接访问共享数据,但需要同步机制(如锁)来避免竞争条件。

3. 创建和销毁

  • 进程:创建和销毁进程的开销较大,因为需要分配和回收独立的内存空间和资源。
  • 线程:创建和销毁线程的开销较小,因为它们共享进程的资源。

4. 并发性

  • 进程:由于进程间相互独立,多进程程序可以充分利用多核CPU,适合CPU密集型任务。
  • 线程:线程适合I/O密集型任务,但由于Python的GIL(全局解释器锁),多线程在CPU密集型任务中无法充分利用多核CPU。

5. 稳定性

  • 进程:进程间相互隔离,一个进程崩溃不会影响其他进程,稳定性较高。
  • 线程:线程共享内存空间,一个线程崩溃可能导致整个进程崩溃,稳定性较低。

6. 通信

  • 进程:进程间通信需要通过IPC机制,较为复杂。
  • 线程:线程间通信可以直接通过共享内存,较为简单,但需要同步机制。

7. Python中的实现

  • 进程 :Python中使用multiprocessing模块来创建和管理进程。
  • 线程 :Python中使用threading模块来创建和管理线程。

8. 示例代码

进程示例
python 复制代码
import multiprocessing

def worker():
    print("Process worker")

if __name__ == "__main__":
    p = multiprocessing.Process(target=worker)
    p.start()
    p.join()
线程示例
python 复制代码
import threading

def worker():
    print("Thread worker")

t = threading.Thread(target=worker)
t.start()
t.join()

小结

  • 进程适合需要高隔离性和CPU密集型任务。
  • 线程适合I/O密集型任务和需要高效通信的场景。

选择使用进程还是线程,取决于具体的应用场景和需求。

二、协程

参考1:https://liaoxuefeng.com/books/python/async-io/coroutine/index.html

参考2:https://liaoxuefeng.com/books/python/async-io/asyncio/index.html

协程(Coroutine) 是一种特殊的函数,能够在执行过程中暂停(挂起)并在稍后恢复执行。它是实现异步编程的核心机制之一,常用于处理 I/O 密集型任务(如网络请求、文件读写等),避免阻塞主线程。

协程与普通函数的区别在于:

  • 普通函数从开始执行到结束,不会中途暂停。
  • 协程可以在执行过程中暂停(通过 awaityield),并在适当的时候恢复执行。

协程的关键特性

  1. 可暂停和恢复

    协程可以在执行过程中暂停,将控制权交还给调用者,稍后再从暂停的地方恢复执行。

  2. 异步非阻塞

    协程通常与异步 I/O 操作结合使用,避免阻塞主线程,提高程序的并发性能。

  3. 轻量级

    协程的上下文切换开销比线程小得多,适合高并发场景。


Python 中的协程

在 Python 中,协程通过 asyncawait 关键字实现:

  • async def:定义一个协程函数。
  • await:暂停协程的执行,等待异步操作完成。
示例
python 复制代码
import asyncio

async def say_hello():
    print("Hello")
    await asyncio.sleep(1)  # 模拟 I/O 操作,暂停 1 秒
    print("World")

# 运行协程
asyncio.run(say_hello())
结果
shell 复制代码
Hello!
(等待约1秒)
World!

协程的工作原理

  1. 事件循环(Event Loop)

    协程的运行依赖于事件循环。事件循环负责调度协程的执行,当协程遇到 await 时,事件循环会暂停当前协程,转而执行其他任务。

  2. 挂起和恢复

    当协程遇到 await 时,它会挂起自己,并将控制权交还给事件循环。事件循环会在异步操作完成后恢复协程的执行。


协程与生成器的关系

协程的实现基于 Python 的生成器(Generator)。生成器通过 yield 关键字实现暂停和恢复,而协程通过 await 实现类似的功能。不过,协程更专注于异步编程,而生成器更常用于惰性计算。


协程的适用场景

  1. I/O 密集型任务
    如网络请求、数据库操作、文件读写等。
  2. 高并发应用
    如 Web 服务器、爬虫、实时数据处理等。
  3. 异步编程
    需要避免阻塞主线程的场景。

示例:并发执行多个协程

py 复制代码
import asyncio

async def io_operation(name, delay):
    print(f"IO操作 {name} 开始")
    await asyncio.sleep(delay)
    print(f"IO操作 {name} 完成")
    return f"{name} 的结果"

async def compute_operation(name, delay):
    print(f"计算操作 {name} 开始")
    await asyncio.sleep(delay)  # 模拟耗时计算
    print(f"计算操作 {name} 完成")
    return f"{name} 的计算结果"

async def network_operation(name, delay):
    print(f"网络操作 {name} 开始")
    await asyncio.sleep(delay)  # 模拟网络请求
    print(f"网络操作 {name} 完成")
    return f"{name} 的网络响应"

# 设计task中有多个协程
async def task(name, delay):
    print(f"Task {name} 启动")
    
    # 并发执行多个异步操作
    results = await asyncio.gather(
        io_operation(f"{name}-IO", delay),
        compute_operation(f"{name}-Compute", delay/2),
        network_operation(f"{name}-Network", delay*1.5)
    )
    
    # 串行执行一些操作
    result2 = await io_operation(f"{name}-Sequential", 10) # delay/3
    result3 = await compute_operation(f"{name}-Final", delay/4)
    
    print(f"Task {name} 完成,获得结果:{results}, {result2}, {result3}")
执行一
python 复制代码
async def main():
    # 并发执行多个协程
    await asyncio.gather(
        task("A", 2),
        task("B", 1),
        task("C", 3),
    )
if __name__ == "__main__":
    asyncio.run(main())
返回一
shell 复制代码
Task A 启动
Task B 启动
Task C 启动
IO操作 A-IO 开始
计算操作 A-Compute 开始
网络操作 A-Network 开始
IO操作 B-IO 开始
计算操作 B-Compute 开始
网络操作 B-Network 开始
IO操作 C-IO 开始
计算操作 C-Compute 开始
网络操作 C-Network 开始
计算操作 B-Compute 完成
计算操作 A-Compute 完成
IO操作 B-IO 完成
网络操作 B-Network 完成
计算操作 C-Compute 完成
IO操作 B-Sequential 开始
IO操作 A-IO 完成
网络操作 A-Network 完成
IO操作 C-IO 完成
IO操作 A-Sequential 开始
网络操作 C-Network 完成
IO操作 C-Sequential 开始
IO操作 B-Sequential 完成
计算操作 B-Final 开始
计算操作 B-Final 完成
Task B 完成,获得结果:['B-IO 的结果', 'B-Compute 的计算结果', 'B-Network 的网络响应'], B-Sequential 的结果, B-Final 的计算结果
IO操作 A-Sequential 完成
计算操作 A-Final 开始
计算操作 A-Final 完成
Task A 完成,获得结果:['A-IO 的结果', 'A-Compute 的计算结果', 'A-Network 的网络响应'], A-Sequential 的结果, A-Final 的计算结果
IO操作 C-Sequential 完成
计算操作 C-Final 开始
计算操作 C-Final 完成
Task C 完成,获得结果:['C-IO 的结果', 'C-Compute 的计算结果', 'C-Network 的网络响应'], C-Sequential 的结果, C-Final 的计算结果
执行二
py 复制代码
async def main():
    tasks = [task("A", 2), task("B", 1), task("C", 3)]
    for i in range(3):
        print(f"Execute Task {i} started")
        task_return = asyncio.create_task(tasks[i % len(tasks)])
        await asyncio.wait_for(task_return, timeout=300)
        print(f"Execute Task {i} completed")

if __name__ == "__main__":
    asyncio.run(main())
返回二
shell 复制代码
Execute Task 0 started
Task A 启动
IO操作 A-IO 开始
计算操作 A-Compute 开始
网络操作 A-Network 开始
计算操作 A-Compute 完成
IO操作 A-IO 完成
网络操作 A-Network 完成
IO操作 A-Sequential 开始
IO操作 A-Sequential 完成
计算操作 A-Final 开始
计算操作 A-Final 完成
Task A 完成,获得结果:['A-IO 的结果', 'A-Compute 的计算结果', 'A-Network 的网络响应'], A-Sequential 的结果, A-Final 的计算结果
Execute Task 0 completed
Execute Task 1 started
Task B 启动
IO操作 B-IO 开始
计算操作 B-Compute 开始
网络操作 B-Network 开始
计算操作 B-Compute 完成
IO操作 B-IO 完成
网络操作 B-Network 完成
IO操作 B-Sequential 开始
IO操作 B-Sequential 完成
计算操作 B-Final 开始
计算操作 B-Final 完成
Task B 完成,获得结果:['B-IO 的结果', 'B-Compute 的计算结果', 'B-Network 的网络响应'], B-Sequential 的结果, B-Final 的计算结果
Execute Task 1 completed
Execute Task 2 started
Task C 启动
IO操作 C-IO 开始
计算操作 C-Compute 开始
网络操作 C-Network 开始
计算操作 C-Compute 完成
IO操作 C-IO 完成
网络操作 C-Network 完成
IO操作 C-Sequential 开始
IO操作 C-Sequential 完成
计算操作 C-Final 开始
计算操作 C-Final 完成
Task C 完成,获得结果:['C-IO 的结果', 'C-Compute 的计算结果', 'C-Network 的网络响应'], C-Sequential 的结果, C-Final 的计算结果
Execute Task 2 completed

小结

协程是一种轻量级的并发编程工具,能够暂停和恢复执行,适合处理 I/O 密集型任务和高并发场景。在 Python 中,协程通过 asyncawait 实现,是异步编程的核心机制之一。

∼ O n e p e r s o n g o f a s t e r , a g r o u p o f p e o p l e c a n g o f u r t h e r ∼ \sim_{One\ person\ go\ faster,\ a\ group\ of\ people\ can\ go\ further}\sim ∼One person go faster, a group of people can go further∼

相关推荐
笨鸟先飞,勤能补拙18 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能19 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂19 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study20 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境21 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境21 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12321 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy123931021621 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb001 天前
一个项目带你入门AI应用开发01
python
0566461 天前
Python康复训练——常用标准库
开发语言·python·学习