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

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

典型的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.dtcms.com/a/356567.html

相关文章:

  • Windows 下 MSYS2 + MinGW-w64 配置 Fyne GUI 编译环境全流程
  • 【计算机408计算机网络】第三章:自底向上五层模型之数据链路层
  • WINTRUST!_GetMessage函数分析之CRYPT32!CryptSIPGetSignedDataMsg函数的作用是得到nt5inf.cat的信息
  • 【算法】链表专题
  • 钉钉补卡事件处理方案
  • uni-app 跨平台项目的 iOS 上架流程:多工具组合的高效协作方案
  • 常见视频封装格式对比
  • 从零开始学习单片机16
  • 数据结构——线性表(链表,力扣中等篇,增删查改)
  • AI接管浏览器:Anthropic发布Claude for Chrome,是效率革命还是安全噩梦?
  • MySQL-内置函数
  • Python 【深度解析】线程与进程:操作系统中多任务的核心机制
  • WebRTC音频QoS方法五(音频变速算法之Expand算法实现)
  • Nodejs介绍
  • FreeRTOS基础知识记录
  • MTK Linux DRM分析(二十)- KMS drm_mm.c drm_vma_manager.c
  • Docker部署单节点使用KRaft存储数据的Kafka与可视化界面Kafka-Map
  • el-table合并列实例
  • 云市场周报 (2025.08.29):解读阿里云g8y、腾讯云Serverless容器与FinOps趋势
  • 神经语言学与脑科学启发的NLP深层分析:从统计拟合到机制理解的范式转变
  • LeetCode 317 离建筑物最近的距离
  • Spring Boot 整合 MongoDB:CRUD 与聚合查询实战
  • vscode优化合集 - Visual Studio Code
  • TensorFlow 面试题及详细答案 120道(51-60)-- 模型保存、加载与部署
  • 字典解密助手ArchiveHelperWpfv1.0.12详细使用说明书
  • [awesome-nlp] docs | 精选NLP资源 | 分类
  • DVWA靶场通关笔记-暴力破解(Impossible级别)
  • Spring框架集成Kakfa的方式
  • 网络与信息安全有哪些岗位:(12)威胁分析师
  • LeetCode算法日记 - Day 25: 数组中的第K个最大元素、库存管理III