举例说同步异步阻塞非阻塞机制

本文通过一个幽默的故事,形象地解释了计算机编程中同步与异步、阻塞与非阻塞的概念,并提供了易于理解的例子来区分这四种不同的工作方式。

 劫匪冲进某花园小别墅,端着AK47,向某衰男甩过去一个袋子:说,快,把现金拿出来给我放进去,这个时候劫匪一直跟着衰男去装钱,看钱装满了他就拿走,此时劫匪是阻塞 的,因为劫匪不能干其他的,得看着这个衰男,免得他搞鬼。

   想象下,如果劫匪等衰男自己去装钱,在钱装满之前,他自己可以到处翻箱倒柜,找点值钱的首饰黄金之类的,那么这个时候劫匪就是非阻塞 的,因为劫匪并没有阻塞在衰男去装钱这个环节上,劫匪可以自由活动做点其他的小买卖。

      再来回顾下上面的情节,如果劫匪在抢劫时需要不时自己看看衰男把钱装好了没有,那么此时劫匪是在同步 工作,因为他在等待衰男把钱装好,自己要不停的关注下。

      当然,劫匪可以给衰男说:把钱装好了,你自己过来找我。这个时候劫匪可以继续等着不做其他的事情,也可以去做点其他的事情,但是劫匪可以不用去看衰男是否把钱装好,因为衰男钱装好了会自动通知劫匪:大哥,钱好了,你拿走吧。这个时候劫匪就是异步 在工作,他提供了一个callback机制给衰男。

 

   可以总结下了:

     同步/异步:   消息通知机制相关=>需要自己关注还是提供callback

     阻塞/非阻塞:等待消息时的状态=>是否可以干别的事情

 

可以相互组合:

同步阻塞: 劫匪看着衰男把钱装好,不能干其他事情

同步非阻塞:劫匪自己也到处搜索宝贝,但是还要不时跑回来看看钱装好没有。

异步非阻塞:劫匪自己也到处搜索宝贝,衰男把钱装好了自动过来告诉劫匪好了

异步阻塞:  劫匪就在那里傻等着,也不用管钱是否装好,衰男把钱装好了自动过来告诉劫匪好了 

<think>好的,用户现在问的是“异步同步阻塞非阻塞的关系”。我需要先理解这两个概念之间的区别和联系。用户之前已经问过关于异步同步通信的问题,现在可能希望更深入理解它们与阻塞/非阻塞的关系。 首先,我需要明确同步异步指的是通信的方式,而阻塞非阻塞更多是指调用方式对线程或进程的影响。同步通信中,调用方需要等待响应,而异步通信则不需要。阻塞调用会暂停当前线程直到完成,非阻塞则立即返回结果或状态。 接下来,我需要解释这四个概念如何相互作用。例如,同步调用可以是阻塞的,比如普通的函数调用;也可以是非阻塞的,但这种情况较少见,可能需要特定机制。而异步调用通常是通过非阻塞的方式实现的,比如回调或事件通知。 然后,我需要举例明不同的组合情况,比如同步阻塞同步非阻塞异步非阻塞等。这有助于用户理解实际应用中这些概念如何结合使用。 还要注意用户可能的误区,比如混淆同步异步阻塞非阻塞的区别。需要强调它们属于不同的层次,同步异步关注的是任务协作模式,而阻塞非阻塞关注的是调用方式对线程的影响。 此外,用户可能希望了解在实际编程中如何选择不同的组合,比如在高并发场景下使用异步非阻塞模式,或者在需要简单实现时使用同步阻塞。需要给出一些典型的应用场景,比如网络编程中的IO模型,如select、poll、epoll等,或者使用线程池处理同步非阻塞的情况。 最后,确保回答结构清晰,分点明,并在最后列出相关问题,帮助用户进一步思考。需要检查是否符合之前的格式要求,比如使用表格、示例代码、注意事项等部分,并确保相关问题部分正确无误。</think>### 同步/异步阻塞/非阻塞的关系 #### **1. 核心定义** | **概念** | **定义** | **关键点** | |------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------| | **同步(Sync)** | 任务协作模式:调用方必须等待操作完成才能继续执行(如函数调用)。 | 调用方与被调用方共享执行流程,结果即时返回。 | | **异步(Async)**| 任务协作模式:调用方无需等待操作完成,通过回调、事件或Future获取结果。 | 调用方与被调用方异步执行,结果延迟返回。 | | **阻塞(Blocking)**| 调用方式:调用方线程被挂起,直到操作完成(如 `read()` 无数据时阻塞)。 | 线程资源被占用,无法执行其他任务。 | | **非阻塞(Non-blocking)**| 调用方式:调用方立即返回结果或状态(如 `read()` 无数据时返回错误码)。 | 线程可继续执行其他任务,需轮询或事件驱动获取结果。 | --- #### **2. 四种组合关系** | **组合** | **行为** | **示例** | |------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------| | **同步阻塞** | 调用方等待操作完成,且线程被挂起。 | 单线程读取文件:`read(fd, buffer, size)` 无数据时阻塞。 | | **同步非阻塞** | 调用方立即返回结果(可能未完成),需主动轮询状态。 | 非阻塞 socket 读取:`recv(fd, buffer, size, MSG_DONTWAIT)` 返回 `EAGAIN`。 | | **异步阻塞** | 调用方等待异步操作完成(如 `Future.get()`),但底层可能非阻塞实现。 | Java 中 `CompletableFuture.get()` 阻塞等待异步任务结果。 | | **异步非阻塞** | 调用方不等待,通过回调或事件驱动获取结果(如事件循环、协程)。 | Node.js 的 `fs.readFile(path, callback)`,回调在 IO 完成后触发。 | --- #### **3. 关键区别与联系** - **层级差异**: - **同步/异步**:描述任务协作模式(调用方与被调用方的交互方式)。 - **阻塞/非阻塞**:描述调用方式对线程/进程的影响(资源占用状态)。 - **独立性**: - 同步调用可以是阻塞非阻塞(如同步非阻塞 IO 需要轮询)。 - 异步调用通常是通过非阻塞实现(如事件驱动、回调机制)。 - **性能影响**: - 阻塞调用可能导致线程资源浪费(如网络 IO 阻塞)。 - 异步非阻塞模式适合高并发(如 Nginx 的事件驱动模型)。 --- #### **4. 典型应用场景** | **场景** | **推荐模式** | **明** | |---------------------------|----------------------|--------------------------------------------------------------------------| | 单线程简单任务(如脚本) | 同步阻塞 | 逻辑清晰,无需复杂状态管理。 | | 高并发网络服务(如Web服务器)| 异步非阻塞 | 通过事件循环(如 epoll、kqueue)处理数万并发连接。 | | GUI 应用(如响应用户输入) | 异步非阻塞 | 避免主线程阻塞导致界面卡顿(如 JavaScript 的事件循环)。 | | 批量数据处理(如日志分析) | 同步非阻塞 + 多线程 | 线程池并行处理任务,避免单线程阻塞。 | | 实时系统(如游戏同步) | 同步阻塞 | 依赖即时响应,容忍低并发。 | --- #### **5. 代码示例** - **同步阻塞(Python)**: ```python # 阻塞式HTTP请求 import requests response = requests.get("https://example.com") # 线程阻塞直到响应返回 print(response.text) ``` - **异步非阻塞(Python + asyncio)**: ```python # 异步HTTP请求 import asyncio import aiohttp async def fetch(): async with aiohttp.ClientSession() as session: async with session.get("https://example.com") as response: return await response.text() # 主线程可继续执行其他任务 loop = asyncio.get_event_loop() content = loop.run_until_complete(fetch()) print(content) ``` - **同步非阻塞(C + 非阻塞 socket)**: ```c // 设置 socket 为非阻塞模式 int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 读取数据(无数据时返回 EAGAIN) char buffer[1024]; ssize_t bytes_read = read(sockfd, buffer, sizeof(buffer)); if (bytes_read == -1 && errno == EAGAIN) { printf("No data available yet.\n"); } ``` --- #### **6. 注意事项** 1. **组合陷阱**: - 同步非阻塞可能导致 CPU 空转(如频繁轮询)。 - 异步阻塞可能失去异步优势(如 `Future.get()` 阻塞主线程)。 2. **系统调用差异**: - 阻塞 IO 调用(如 `read()`)由内核管理线程挂起。 - 非阻塞 IO 需用户层主动轮询或结合 `select/poll/epoll`。 3. **调试复杂度**: - 异步代码调试困难(如竞态条件、状态维护)。 - 同步代码逻辑简单但扩展性差。 ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值