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

阻塞,非阻塞,同步,异步的理解

典型的IO分为两个阶段:

数据的准备:根据系统IO操作的就绪状态,阻塞,非阻塞(从外部向内核缓冲区拷贝数据,应用进程的状态
内核缓冲区上是否有数据可读,数据没有准备好,应用调用recv阻塞住,应用调用函数立即返回非阻塞
socket上没有数据阻塞住,直到有数据
数据读写:根据应用程序和内核的交互方式,同步,异步
业务层面的一个逻辑处理,业务层面也有同步和异步之分

应用程序调用recv函数向内核发送IO请求时,内核缓冲区的数据还没有准备好,此时应用程序阻塞在请求的状态,等待recv函数返回就是“阻塞”。随后当内核缓冲区中的数据准备好以后,应用程序再通过recv函数将数据搬运到用户态就是“同步”。

关于 “阻塞” 的理解:正确

当应用程序调用 recv 函数时,如果内核缓冲区中没有数据(或数据不足),内核会让当前进程进入阻塞状态(暂停执行,让出 CPU 资源),直到内核缓冲区中有足够数据后,才会唤醒进程继续执行 recv 操作。这个 “暂停等待” 的状态,就是阻塞

简单说:“阻塞” 描述的是进程在等待 IO 事件(数据就绪)时的状态—— 是否会暂停执行、让出 CPU。

关于 “同步” 的理解:正确,但需明确核心

当内核缓冲区数据准备好后,recv 函数会负责把数据从内核态缓冲区拷贝到用户态缓冲区,这个拷贝过程需要应用程序 “主动参与”(通过 recv 调用触发,并且进程会等待拷贝完成后才继续执行)。这种 “IO 操作的完成(包括数据拷贝)需要应用程序主动等待并参与” 的模式,就是同步 IO

核心点:“同步” 的关键是数据从内核到用户态的拷贝过程,需要应用程序等待并主导完成recv 是典型的同步 IO 函数,因为它不仅要等数据就绪,还要亲自完成数据拷贝,整个过程需要应用程序阻塞(或轮询)等待。

额外澄清:阻塞 vs 同步的关系

两者不是同一维度的概念,但常被一起讨论:

  • 阻塞 / 非阻塞:描述进程在等待 IO 事件(如数据就绪)时的状态(是否暂停执行)。
  • 同步 / 异步:描述 IO 操作的完成方式(是否需要应用程序参与数据拷贝,以及是否需要等待整个过程完成)。
  • recv 在默认情况下是 “阻塞同步 IO”:既会阻塞等数据,又需要应用程序参与拷贝。
  • 如果用非阻塞模式调用 recv(通过 fcntl 设置),则是 “非阻塞同步 IO”:数据没准备好时不阻塞(直接返回错误),但数据就绪后仍需应用程序通过 recv 完成拷贝(同步特性不变)。
  • 异步 IO(如 Linux 的 io_uring 或 Windows 的 IOCP)则不同:应用程序发起 IO 请求后就可以做其他事,内核会自己完成 “等数据 + 拷贝数据”,最后通过回调 / 信号通知应用程序 “操作已完成”,全程不需要应用程序等待或参与拷贝 —— 这才是 “异步”。

应用程序调用recv函数向内核发送IO请求时,内核缓冲区的数据还没有准备好,此时应用程序判断recv函数的返回值,不阻塞在请求的状态,就是“非阻塞”。随后当内核缓冲区中的数据准备好以后,内核通过应用程序注册的函数将数据拷贝到用户态通知应用程序拿走,这就是“异步”。

关于 “非阻塞” 的理解:

当应用程序以非阻塞模式调用 recv 时,如果内核缓冲区没有数据,recv 不会让进程进入阻塞状态(不会 “卡住等待”),而是立即返回一个错误码(比如 Linux 中的 EAGAIN 或 EWOULDBLOCK),告诉应用程序 “当前没数据,你先去忙别的”。

这种 “不等数据就绪,直接返回状态” 的模式,就是非阻塞。它的核心是:进程在 IO 操作未就绪时,不会暂停执行,而是可以继续处理其他任务(比如隔一会儿再重试 recv,或处理其他逻辑)。

关于 “异步” 的理解:完全正确

异步 IO 的核心是 “内核全程包办,应用程序彻底不参与等待和拷贝”:

  1. 应用程序通过特定接口(如 aio_read 或 io_uring)发起 IO 请求,并注册一个回调函数(告诉内核 “数据准备好并拷贝完成后,就调用这个函数通知我”);
  2. 发起请求后,应用程序可以立即去做其他事,完全不需要等待(既不阻塞,也不用轮询);
  3. 当内核缓冲区数据就绪后,内核会主动将数据从内核态拷贝到用户态缓冲区,然后通过回调函数(或信号)通知应用程序 “数据已经备好,你可以直接用了”。

整个过程中,应用程序既不用等待数据就绪,也不用参与数据拷贝,只是在最后接收 “完成通知”—— 这就是异步的本质。

一句话总结区别:

  • 非阻塞:IO 未就绪时不阻塞,但数据就绪后仍需应用程序主动调用 recv 完成拷贝(同步特性不变);
  • 异步:应用程序发起请求后彻底 “不管”,内核自己搞定 “等数据 + 拷贝数据”,最后通知结果(全程无需应用程序参与等待或拷贝)。
http://www.xdnf.cn/news/19029.html

相关文章:

  • Linux -- 进程间通信【命名管道】
  • 【golang长途旅行第34站】网络编程
  • GPT-5原理
  • mybatis.xml直接读取配置文件(application.yml)中的数据
  • 图扑 HT 农林牧数据可视化监控平台
  • 计算机视觉----opencv(图像轮毂绘制(大小选择,排序,外接图形绘制),轮廓的近似,模板的匹配)
  • 10迁移TiDB数据库数据到GaussDB
  • 前端vue3入门学习
  • OSS Nginx 反代提示 SignatureDoesNotMatch
  • 【面试系列】谈谈你对数据库ACID的理解
  • 2023年12月GESP5级C++真题解析,包括选择判断和编程
  • 【MFC教程】C++基础:01 小黑框跑起来
  • 嵌入式学习 day61 DHT11、I2C
  • 数据分析编程第六步:大数据运算
  • MySQL-索引(下)
  • 【C语言初阶】指针_野指针,指针运算
  • 大白话说 AI 编程 Trae,小白进!
  • 【计算机网络】前端基础知识Cookie、localStorage、sessionStorage 以及 Token
  • 【上位机数据转换】数据结构原理及大小端
  • 0基础学智能体/工作流 从入门到精通(超详细课程)
  • Redis面试题--介绍下Redis几种集群模式
  • 序列容器(vector,deque,list)
  • 旧衣物回收小程序功能模块设计分析
  • 华为无线AC主备配置案例
  • CMake构建学习笔记22-libxml2库的构建
  • 不止于价格,DigitalOcean、AWS和Linode该选谁?
  • Vue3+TS+Element-Plus+el-tree创建树节点
  • 【2025 完美解决】Failed connect to github.com:443; Connection timed out
  • Charles打开后,Pc电脑端浏览器显示Not implemented或没有网络
  • 【计算机组成原理·信息】2数据①