异步机制(Asynchronous) -- (三)和同步机制的本质区别

本文探讨了同步和异步机制的区别,通过对比同步代码和异步代码(以Mina为例)的执行流程,揭示了异步编程中回调函数的使用和线程上下文切换的特点。同步机制中,线程在等待操作完成时会被挂起,而异步机制则通过回调函数和多线程实现任务间的解耦,但可能导致代码组织的复杂性增加。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

矛盾很久,不确定是否该用“本质”这个词,觉着自己好像还没资格这么说。其实,这篇探讨的是换个角度看待同步和异步的差异。

 

为了分析同步和异步的区别,还是以前两篇中出现过的Client发送request和接收response的程序为例。如果是同步机制的程序,大致应该是这样的(只是一些伪代码):

可以看出,整片代码中有多个功能函数,并且他们被顺序的组合成了这一大块代码。

如果是异步的程序,写法却是这样的(也是伪代码,不过模仿的是Mina程序):

在这些代码中,也能够找到同步代码中出现的那些函数,所不同的是,这些函数的大部分都变成了回调,更显著的区别在于,这些函数已经不是也不能顺序的放在了同一个代码块中了。所以,在同步机制中非常完整,非常有条理的代码在异步机制中会被切割得支离破碎。这就回答了第一篇 中最后的那个问题,为什么大家都不太喜欢用异步机制,因为它确实不够友好,也不太符合人一般的思维习惯。

再来琢磨琢磨这些代码在执行的时候发生了什么,这里很有趣。
先从同步的代码说起。当代码执行connectServer这个函数的时候,程序会去尝试连接远程的服务器,这期间,线程被阻塞了,因此内核将线程挂起,将线程运行时的一些context(比如寄存器)给保存在某个地方,然后运行另外一个线程,当连接成功以后,线程又被唤醒,将它的context重新恢复,然后继续运行。同样的,当运行到readResponse()的时候,内核去网卡缓冲区中读数据,这时候数据还没到,于是又将线程挂起,切换并保存context,然后运行另一个线程,当网卡缓冲区有数据后,线程被唤醒,恢复context,然后继续运行。

 

如果是异步程序呢?比如执行connectServer完后返回一个ConnectFuture,这时候连接还没有完成。于是我们向Mina注册一个回调函数ConnectListener,它告诉Mina当连接完成后要去调用writeRequest函数。这里存在一个问题,Mina怎么知道writeRequest应该向哪个socket写入数据呢?诀窍在于connectServer返回的ConnectFuture。它被当做参数传入了回调函数中,而在ConnectFuture中保存了目标server对应的Socket(就是我们代码中的那个Session)。
再比如当request被写出去后,Mina是通过Java Nio的Select来接收response的,当socket中有数据写入时,messageReceived就会被调用。但是,这个函数是如何知道message是从哪个socket中读到的呢?因为Mina会将对应的socket作为参数写入。那么,Mina又是如何知道读到的message是哪个request的呢?Mina是不会知道的,所以,正如第二篇 写的那样,我们必须自己维护一个ID号,通过ID号找到对应的request。

 

好吧,我承认上面的这几段比较看着还是挺乱的。让我再把思路理顺一些。对于同步的程序,只需要一个线程顺序的执行所有的功能函数,在执行的过程中,线程一旦被阻塞,就会被内核挂起,直到它能够继续走下去,这期间,内核会负责切换线程的上下文。而对于异步程序,首先,整个代码会被切割成不同的功能函数作为回调,它们之间的执行顺序没有保证;其次,不会只有一个线程完成所有的任务,比如在第二篇 的Hadoop RPC中,读和写是分别由两个线程完成的,而在Mina中,它内部也有一定数量的工作线程,上述的那些回调函数可能会被不同的线程执行;最后,即便这些回调函数被不同的线程执行,但是,在他们的运行过程中,也发生了上下文的切换,比如必须告诉ConnectListener是哪个socket连接成功了,要告诉messageReceived是从哪socket读取的数据,要告诉handleResponse这个response对应于哪个request,只是,和同步机制不同的是,这些上下文的切换是由提供异步机制的程序完成的(比如Mina,比如Hadoop RPC),而不是内核提供的。

 

未完待续~

<think>我们被要求回答关于AJAX同步异步的区别及工作原理的问题。根据引用资料,我们可以总结如下:1.**同步请求(Synchronous)**:-发送一个请求后,必须等待服务器响应结束(即请求完成)才能发送下一个请求。-在等待期间,用户不能进行其他操作,整个页面会被锁定(阻塞),用户体验较差。-同步请求会刷新整个页面。2.**异步请求(Asynchronous)**:-发送一个请求后,不需要等待服务器响应,可以继续发送其他请求。-通过回调函数处理服务器的响应,实现局部刷新(只更新页面的部分内容),不会阻塞用户操作。-用户体验更好,因为页面不会完全刷新,用户可以在等待服务器响应的同时继续与页面交互。**工作原理**:-AJAX通过`XMLHttpRequest`对象(现代浏览器中也可以用`fetch`API)与服务器进行异步通信。-基本步骤(四步操作):1.创建`XMLHttpRequest`对象。2.设置请求方法URL,并指定是否异步(通过`open`方法的第个参数,`true`表示异步,`false`表示同步)。3.设置回调函数(通过`onreadystatechange`事件),在请求状态改变时处理响应。4.发送请求(`send`方法)。在回调函数中,我们检查请求的状态(`readyState`)响应的状态码(`status`),当请求完成且成功时(`readyState`为4,`status`为200),我们可以获取响应数据并更新页面的部分内容。**引用说明**:-引用[1][3]解释了同步异步的基本概念以及区别。-引用[3][4]详细描述了AJAX的工作原理,包括四步操作。-引用[2][5]提供了更多关于使用场景代码实现的信息。现在,我们按照要求生成相关问题。</think>### AJAX同步与异步的区别及工作原理 #### **同步请求(Synchronous)** 1. **工作原理**: 发送请求后,浏览器会**阻塞用户操作**,必须等待服务器返回完整响应才能继续执行后续代码。期间页面处于“冻结”状态。 代码示例: ```javascript let xhr = new XMLHttpRequest(); xhr.open('GET', '/api/data', false); // 第个参数false表示同步 xhr.send(); console.log(xhr.responseText); // 需等待响应完成后才执行 ``` 2. **核心特点**: - 阻塞式交互,用户体验差 - 刷新整个页面 - 适用场景:需严格顺序执行的操作(如支付确认)[^3][^5] --- #### **异步请求(Asynchronous)** 1. **工作原理**: 通过事件驱动模型实现非阻塞通信: - 创建`XMLHttpRequest`对象 - 绑定`onreadystatechange`回调函数 - 服务器返回数据后触发回调,局部更新DOM ```javascript let xhr = new XMLHttpRequest(); xhr.open('GET', '/api/data', true); // true表示异步 xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { document.getElementById("content").innerHTML = xhr.responseText; // 局部刷新 } }; xhr.send(); console.log("请求已发送,无需等待"); // 立即执行 ``` 2. **核心特点**: - 非阻塞式交互,用户可继续操作页面 - 仅刷新局部内容(如动态加载评论) - 通过回调函数/`Promise`处理响应[^1][^4] --- #### **关键区别总结** | **特性** | 同步请求 | 异步请求 | |----------------|----------------------------|----------------------------| | **用户体验** | 页面卡顿,操作被阻塞 | 流畅,用户可继续交互 | | **刷新范围** | 整个页面重载 | 局部DOM更新 | | **代码执行** | 顺序执行,需等待响应 | 非阻塞,回调函数处理结果 | | **适用场景** | 强依赖顺序的操作(如表单提交)| 动态加载数据、实时搜索等[^2] | #### **AJAX技术本质** 基于`XMLHttpRequest`对象(或现代`fetch API`),利用JavaScript在后台与服务器交换数据,实现**无刷新更新页面**。其异步模式通过事件循环机制实现:当主线程发送请求后,由浏览器网络线程处理通信,响应到达后通过回调函数通知主线程[^4][^5]。 > 优势:提升用户体验,减少带宽消耗; > 局限:增加服务器压力,SEO不友好[^3]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值