同步、异步转化和任务执行

同步异步探秘

正如动静是相对的概念,有了它们,世界才充满盎然生气;变和不变也是哲学上的对立统一,在代码的世界里也一样;同步异步呢?在这一篇文字里面已经很粗略地提到了同步和异步各自有些什么好处,接下来,我不妨说一些同步和异步互相转化的故事。

 

先来看看这一段代码:

 

setTimeout(function(){
	while(true){
		alert("In");
	}
},0);
while(true){
	alert("Out");
}

 

它的输出应该是怎样的呢?你可以试一试。

不同浏览器下它的表现不同,有的浏览器下一直显示In的弹出框;有的浏览器下一直显示Out的弹出框;还有的浏览器下先显示一个Out,再不断显示In的弹出框。

那是不是可以这样理解:

上面的代码本意是想描述一个页面的JavaScript代码进行类似于并行线程的执行(setTimeout调用的方法,似乎就是一个异步执行的方法,它本意是不阻止主流程的执行的),可是实际运行的结果发现,原来浏览器运行JavaScript,所谓的异步,只是对开发人员和用户的一个欺骗,世界只是看起来这个样子——实际上,在JavaScript的世界里,其实根本就是“单线程”的嘛!

其实,这是无所谓欺骗的,就如同对于单CPU的机器来说,所谓的多进程,其实也只有一个CPU轮流执行队列里的指令。只是这个世界本来就是那么残酷,也许是我们都看错了……

 

 

同步Ajax和异步Ajax

Ajax通常都是异步的,同步的Ajax调用会将浏览器当前页面挂起,拒绝一切用户操作,直至响应到达:

 

var req = new  XMLHttpRequest();
req.open("GET", url, true);  //true表示异步,false表示同步
req.onreadystatechange  =  callback;
req.send();

 

 

JavaScript的一个悲剧

在JavaScript中,没有一个方法可以让主线程休息一段时间(Java中有sleep和wait),也就是说,如果我想在某一个执行逻辑中,休息一会、等待一会,这样的实现都会变得很困难(Jscex就是用来解决这样的问题的)。这似乎是JavaScript的一个天生的重大缺陷。

Jscex带来的最大好处,就在于可以用同步的思维和编码,来解决异步的问题:

 

var moveAsync = eval(Jscex.compile("$async", function(e, startPos, endPos, duration) {
    for (var t = 0; t < duration; t += 50) {
        e.style.left = startPos.x + (endPos.x - startPos.x) * (t / duration);
        e.style.top = startPos.y + (endPos.y - startPos.y) * (t / duration);
        $await(Jscex.Async.sleep(50));
    }
    e.style.left = endPos.x;
    e.style.top = endPos.y;
}));

 

 

Barrier模式

Barrier是一道篱笆,所有的不同异步线程,都先先后后运行完毕以后(都撞到了篱笆上),再汇成一束主流程继续往后走:


JDK的CyclicBarrier类就是用来实现这个模式的(A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.):

 

class Solver {
	final int N;
	final float[][] data;
	final CyclicBarrier barrier;

	class Worker implements Runnable {
		int myRow;

		Worker(int row) {
			myRow = row;
		}

		public void run() {
			while (!done()) {
				processRow(myRow); //执行某一行的逻辑

				try {
					barrier.await(); //该行逻辑执行完毕后,告知一下
				} catch (InterruptedException ex) {
					return;
				} catch (BrokenBarrierException ex) {
					return;
				}
			}
		}
	}

	public Solver(float[][] matrix) {
     data = matrix;
     N = matrix.length;
     barrier = new CyclicBarrier(N,
                                 new Runnable() {
                                   public void run() {
                                     mergeRows(...); //在每一行都处理完毕以后,执行一个merge操作
                                   }
                                 });
     for (int i = 0; i < N; ++i)
       new Thread(new Worker(i)).start();

     waitUntilDone();
   }
}

 

而在JavaScript中,也可以实现类似的效果:

var count = 3;
for(var i=0; i<=count; i++){
	setTimeout(function(){
		doXXX(); // 执行任务
		count --; //每个子任务执行完毕后都标记一下
		if(!count)
			doFinalXXX(); //Barrier的汇总任务
	},0);
}

 

如果有了Jscex,实现可以更简洁:

function (taskA, taskB, taskC) {
    $await(Jscex.Async.parallel(taskA, taskB)); //先并行执行任务A、B
    $await(taskC); //在A、B都完成后再执行C
}

 

 

Future和Promise

Future、Promise是用于并发编程的一种同步构造。它们表示一个对象,这个对象用来作为一次计算的结果的代理,而该结果被初始化为未知,因为这个对象产生时计算还没有结束(或还没有开始)。

Java中有Future可以帮助实现:

 

ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Object> task = new Callable<Object>() {
	public Object call() throws Exception {
		doXXX();
		return result;
	}
};
Future<Object> future = executor.submit(task);
boolean isCancelled = future.isCancelled(); //查询状态,调用cancel方法可以取消任务
boolean isDone = future.isDone(); //查询状态
Object res = future.get(); // 等待至完成

 

JavaScript可以实现成类似这样子:

 

 

Promise.when(promise1, promise2).then(function (data1, data2) {...});

 

具体请参见这里

 

文章系本人原创,转载请注明出处和作者

<think>嗯,用户问的是“异步通信与同步”,我需要先理解这个问题。他们可能是在问同步通信异步通信的区别,或者是想了解两者之间的联系。首先,我得确认用户的需求是什么。 同步通信异步通信是计算机科学中的常见概念,尤其是在网络编程、操作系统、多线程等方面。用户可能是在学习这些概念时遇到了疑问,或者在实际开发中遇到了相关的问题,需要明确两者的区别应用场景。 接下来,我需要回忆同步异步通信的基本定义。同步通信通常指发送方接收方在通信过程中需要相互等待,比如在函数调用中,调用方会阻塞直到操作完成。而异步通信则是发送方发出请求后继续执行其他任务,不等待接收方的响应,接收方处理完请求后可能会通过回调、事件等方式通知发送方。 然后,我需要比较它们的区别,包括阻塞与非阻塞、资源利用、复杂度、适用场景等。还要考虑它们的联系,比如异步通信有时是为了提高效率而设计的,可能基于同步机制实现。 用户可能还想知道在哪些情况下选择同步,哪些情况下选择异步。例如,同步通信适用于需要实时响应、数据一致性要求高的场景,如在线支付系统。异步通信适用于高并发、需要高吞吐量的场景,如消息队列、日志处理等。 另外,可能需要提到同步异步在不同层面上的表现,比如在函数调用、网络请求、操作系统调用(如IO操作)中的具体应用。比如,同步IO会阻塞进程直到数据准备好,而异步IO允许进程在数据准备期间执行其他任务。 还要考虑用户可能的误区,比如混淆同步/异步与阻塞/非阻塞的概念。虽然相关,但它们是不同的维度。同步/异步关注的是请求的发起完成方式,而阻塞/非阻塞关注的是等待时的状态。 需要举一些例子来帮助理解。比如同步通信的例子:打电话时双方必须同时在线,等待对方接听。异步通信的例子:发邮件,发送后可以做其他事情,对方阅读后回复。 另外,可能还需要提到技术实现,比如回调函数、事件循环、Future/Promise、消息队列等机制如何支持异步通信。同时,同步通信可能更简单,但容易导致资源浪费,而异步更复杂,但能提高效率。 用户可能没有明确说明他们的背景,比如是开发者、学生,还是其他角色。因此,回答需要兼顾理论实际应用,提供清晰的对比示例,确保不同层次的用户都能理解。 最后,要确保回答结构清晰,分点列出区别、联系、示例适用场景,并按照用户的要求生成相关问题。同时,遵循用户提供的格式,避免使用Markdown,保持口语化,但在这里需要换为正式的回答。</think>### 同步通信与异步通信的区别与联系 #### **1. 核心区别** | **特性** | **同步通信** | **异步通信** | |-----------------------|----------------------------------------|----------------------------------------| | **等待机制** | 发送方必须等待接收方响应完成再继续执行。 | 发送方无需等待接收方响应,直接继续执行后续任务。 | | **时序要求** | 严格依赖实时响应(如电话通话)。 | 允许延迟响应(如电子邮件)。 | | **资源占用** | 可能阻塞线程/进程,资源利用率较低。 | 非阻塞,资源利用率高(如通过回调或事件驱动)。 | | **复杂度** | 实现简单,逻辑直观。 | 实现复杂(需处理回调、状态维护等)。 | | **数据一致性** | 强一致性,结果即时可见。 | 最终一致性,结果可能延迟生效。 | | **典型场景** | 需实时反馈的场景(如在线支付验证)。 | 高并发、批量处理场景(如消息队列、日志采集)。 | --- #### **2. 联系** - **目标一致**:均用于实现不同组件/系统间的数据交换。 - **可相互转化**:异步通信可通过封装实现同步语义(如 `Future.get()` 阻塞等待结果),同步通信也可通过多线程模拟异步行为。 - **底层依赖**:异步通信通常基于同步机制(如底层网络协议仍需同步传输数据包)。 --- #### **3. 关键技术对比** | **技术点** | **同步通信** | **异步通信** | |-----------------------|----------------------------------------|----------------------------------------| | **调用方式** | 直接函数调用、阻塞式IO。 | 回调函数、事件监听、消息队列、协程。 | | **错误处理** | 错误直接抛出或返回码。 | 需通过回调或异常捕获机制传递错误。 | | **性能瓶颈** | 高延迟场景易导致资源浪费(如等待IO)。 | 高吞吐量场景更高效,但需管理复杂状态。 | | **调试难度** | 易调试(线性执行流)。 | 难调试(非线性、多线程/事件驱动)。 | --- #### **4. 典型示例** - **同步通信**: ```python # 同步HTTP请求 import requests response = requests.get("https://example.com") # 阻塞直到响应返回 print(response.text) ``` - **异步通信**: ```python # 异步HTTP请求(使用asyncio) 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() asyncio.run(fetch()) # 主线程可继续执行其他任务 ``` --- #### **5. 适用场景** | **场景** | **推荐模式** | **说明** | |---------------------------|------------------|--------------------------------------------------------------------------| | 实时性要求高(如游戏同步) | 同步通信 | 依赖即时响应,容忍低并发。 | | 高吞吐量场景(如订单处理) | 异步通信 | 允许延迟响应,需处理大量并发任务。 | | 资源受限环境(如嵌入式系统)| 同步通信 | 简化逻辑,避免异步状态管理开销。 | | 分布式系统(如微服务通信) | 异步通信 | 通过消息队列解耦服务,提升系统容错性。 | | 数据一致性要求严格 | 同步通信 | 如数据库事务提交需即时确认结果。 | --- #### **6. 注意事项** - **同步陷阱**: - 阻塞操作可能导致线程/进程“卡死”(如网络超时未设置超时机制)。 - 在GUI应用中使用同步通信需避免主线程阻塞(如使用后台线程)。 - **异步挑战**: - 回调地狱(Callback Hell)问题(可通过协程或Promise链解决)。 - 状态一致性维护困难(如分布式异步任务需引入事务日志)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值