当前位置: 首页 > news >正文

并发编程核心概念详解:进程、线程与协程的本质与差异

目录

 一、什么是进程?

1.1 定义

1.2 进程的特点

 1.3 进程的状态

 二、什么是线程?

2.1 定义

2.2 线程的优缺点

2.3 进程和线程之间的区别和联系

三、什么是协程?

 3.1 定义

3.2 与多线程相比,协程的优势

 3.3 与虚拟线程的关键区别

 

3.4 代码示例(python)


        进程(Process):是资源分配的最小单位,一个进程可以有多个线程,多个线程共享进程的堆和方法区资源,不共享栈、程序计数器。

        线程(Thread):是任务调度和执行的最小单位,线程并行执行存在资源竞争和上下文切换的问题。

        协程(Coroutine):是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。


 一、什么是进程?

1.1 定义

        打开微信会产生一个进程,打开QQ会产生一个进程,电脑上运行的程序都是进程。

        直观点说,保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,上级挂靠单位是操作系统。操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位

        进程之间无法直接访问彼此的资源。

1.2 进程的特点

  • 独立性:每个进程都有自己的地址空间,彼此独立,互不影响。
  • 资源分配单元:操作系统为每个进程分配资源,如内存、文件句柄等。
  • 隔离性:进程之间的通信需要借助操作系统提供的进程间通信(IPC)机制,如管道、消息队列、共享内存等。  一个进程的错误不会影响其他进程的稳定性。

 管道

        管道是操作系统中最古老、最基础的 IPC 机制,本质是一个在内核中创建的临时缓冲区,用于实现两个进程之间的单向数据传输。它的工作方式类似日常生活中的 “水管”:一个进程作为 “写入端” 向管道发送数据,另一个进程作为 “读取端” 从管道接收数据,数据按照先进先出(FIFO)的顺序流动。

消息队列

        消息队列是一种更高级的 IPC 机制,它在 kernel 中创建一个具有标识符的消息链表,允许进程按 “消息” 为单位发送和接收数据。与管道的字节流不同,消息队列中的每个数据单元是结构化的 “消息”,包含消息类型和数据内容两部分,接收进程可根据消息类型选择性读取,实现按类型分拣数据的功能。   类似邮局的邮件处理。

  • 管道适合简单的单向数据传输,如命令行管道、父子进程的临时数据交换,尤其适合传输连续的字节流(如日志输出、数据备份);​
  • 消息队列适合需要按类型区分数据、异步通信或跨无亲缘关系进程的场景,如分布式系统中的模块协作、多任务调度系统的任务分发等。

 1.3 进程的状态

进程通常有以下几种状态:

  • 创建(New):进程刚被创建,由于其他进程正占有CPU所以得不到执行,只能处于初始状态。
  • 就绪(Ready):只有处于就绪状态的经过调度才能到执行状态。
  • 运行(Running):进程正在执行。
  • 阻塞(Blocked):进程等待某个事件(如I/O操作)完成。这时,即使给它CPU控制权,它也无法运行。
  • 终止(Terminated):进程执行完毕或被强制结束。

 


 二、什么是线程?

2.1 定义

        线程,有时被称为轻量级进程(Lightweight Process,LWP),是操作系统调度(CPU调度)执行的最小单位

         一个进程可以包含多个线程,它们共享进程的资源,如内存、文件句柄等,但有自己的栈和寄存器,这样可以确保线程的控制流是相对独立的。

2.2 线程的优缺点

①优点

  • 一个进程中可以同时存在多个线程
  • 让进程具备多任务并行处理能力
  • 同进程下的各个线程之间可以共享进程资源 (同进程内的多线程通信十分简单高效)
  • 更轻量与高效

②缺点

  • 因为进程资源共享,所以会产生资源竞争,需要通过锁机制来协同
  • 当进程中的一个线程奔溃时,会导致其所属进程的所有线程奔溃(一般游戏的用户设计不会采用多线程方式)

2.3 进程和线程之间的区别和联系

①区别:

  • 调度线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

  • 并发性不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

  • 资源:进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈;
  • 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。但是进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。进程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个进程死掉就等于所有的线程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些

 ②联系:

  • 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

  • 资源分配给进程,同一进程的所有线程共享该进程的所有资源;

  • 处理机分给线程,即真正在处理机上运行的是线程

  • 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。


三、什么是协程?

 3.1 定义

        协程,又称微线程纤程,是一种用户态的轻量级线程,完全由用户程序(而非操作系统内核)控制调度。它不像进程那样拥有独立的内存空间,也不像线程那样需要操作系统进行调度切换。

        它依赖 “协作式调度” 机制:一个协程需要主动通过yieldawait等关键字让出 CPU,其他协程才能获得执行机会。
        协程通常运行在单一线程内,共享该线程的内存资源,因此创建和切换成本极低(无需内核态上下文切换),适合在有限资源下实现高并发(如单线程内创建数万协程)。

3.2 与多线程相比,协程的优势

        ①极高的执行效率

                因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显;

        ②不需要多线程的锁机制

                因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

 3.3 与虚拟线程的关键区别

维度协程(Coroutine)虚拟线程(Virtual Thread)
调度机制协作式调度:需主动yield/await让出 CPU抢占式调度:JVM 可强制切换虚拟线程(类似 OS 线程)
与线程的关系运行在单一线程内,共享线程资源依赖载体线程(OS 线程)执行,可动态绑定不同载体线程
编程模型需显式使用async/await等语法标记切换点兼容传统线程 API(如RunnableThread),无需修改代码
语言依赖依赖编程语言原生支持(如 Python、Go、Kotlin)主要由 Java JVM 实现,是 JVM 层面的抽象
阻塞处理若协程内存在阻塞调用(如同步 IO),会阻塞整个线程虚拟线程的阻塞会被 JVM “翻译” 为非阻塞操作,不阻塞载体线程

3.4 代码示例(python)

import asyncio# 定义第一个协程函数
async def coroutine_1():for i in range(5):print(f"协程1: 输出 {i}")# 让出控制权,允许其他协程执行await asyncio.sleep(0.2)# 定义第二个协程函数
async def coroutine_2():for i in range(5):print(f"协程2: 输出 {i}")# 让出控制权,允许其他协程执行await asyncio.sleep(0.1)# 主函数,并发运行两个协程async def main():# 创建两个协程任务task1 = asyncio.create_task(coroutine_1())task2 = asyncio.create_task(coroutine_2())# 等待两个任务都完成await asyncio.gather(task1, task2)# 运行主函数
asyncio.run(main())

await asyncio.sleep(0.1)让出 CPU 控制权

asyncio.create_task()创建可并发执行的任务

asyncio.gather()等待所有任务完成

        协程在子程序内部是可中断的,然后转而执行别的子程序,在适当的时候再返回来接着执行。 

http://www.lryc.cn/news/588406.html

相关文章:

  • 融合竞争学习与高斯扰动的多目标加权平均算法(MOWAA)求解多无人机协同路径规划(多起点多终点,起始点、无人机数、障碍物可自定义),提供完整MATLAB代码
  • 【抖音滑动验证码风控分析】
  • 【人工智能99问】什么是深度学习?(2/99)
  • RK3568/3588 Android 12 源码默认使用蓝牙mic录音
  • 显示器核心三要素详解:刷新率、分辨率、色深
  • PHP password_get_info() 函数
  • 渗透笔记1-4
  • Java 树形结构、层级结构数据构建
  • 【LeetCode 热题 100】94. 二叉树的中序遍历——DFS
  • 第四章 uniapp实现兼容多端的树状族谱关系图,剩余组件
  • 用基础模型构建应用(第九章)AI Engineering: Building Applications with Foundation Models学习笔记
  • GaussDB in的用法
  • Elasticsearch 9.x 升级变化
  • C++后端面试八股文
  • 【postgresql数据库实现表的树结构查询】
  • 乳化硅油市场报告:深度解析与未来趋势
  • 信息收集的基本流程
  • 非阻塞写入核心:asyncio.StreamWriter 的流量控制与数据推送之道
  • 电流驱动和电压驱动的区别
  • UV vs Pip:Python 包管理的革命性进化
  • redis实现红锁
  • 迅为八核高算力RK3576开发板摄像头实时推理测试 ppyoloe目标检测
  • Java 大视界 -- 基于 Java 的大数据可视化在城市地下管网管理与风险预警中的应用
  • ThreadLocal结构
  • 在Maven多模块项目中进行跨模块的SpringBoot单元测试
  • 考研408《计算机组成原理》复习笔记,第三章(4)——主存与CPU连接(字、位扩展)
  • 研究人员利用提示注入漏洞绕过Meta的Llama防火墙防护
  • 开源软著源代码生成工具(自制)
  • Java行为型模式---模板方法模式
  • 实现高效、可靠的基于骨骼的人体姿态建模(第二章 基于三维人体姿态回归的语义图卷积网络)