异步执行和同步执行之间的区别是什么?
当前回答
我创建了一个动图来解释这一点,希望能有所帮助: 看,第3行是异步的,其他是同步的。 在行3之前的所有行都应该等到行完成它的工作,但因为行3是异步的,下一行(行4),不要等待行3,但行5应该等待行4完成它的工作,行6应该等待行5和7的6,因为行4,5,6,7不是异步的。
其他回答
同步与异步
同步和异步操作是关于下一个任务相对于当前任务的执行顺序。
让我们看一个例子,Task 2是当前任务,Task 3是下一个任务。Task是堆栈(方法帧)中的原子操作方法调用。
同步
意味着任务将逐个执行。当前任务完成后才会启动下一个任务。任务2完成后才启动任务3。
单线程+同步-顺序
通常执行。
伪代码:
main() {
task1()
task2()
task3()
}
多线程+同步-并行
屏蔽。
阻塞意味着线程只是在等待(尽管它可以做一些有用的事情)。例如:Java ExecutorService[About] and Future[About])伪代码:
main() {
task1()
Future future = ExecutorService.submit(task2())
future.get() //<- blocked operation
task3()
}
异步
暗示任务立即返回控制,并承诺执行代码,稍后通知结果(例如。回调功能)。即使任务2没有完成,任务3也会执行。异步回调,完成处理程序
单线程+异步-并发
使用回调队列(消息队列)和事件循环(运行循环,循环器)。事件循环检查线程堆栈是否为空,如果为真,则将第一个项目从回调队列推入线程堆栈,并再次重复这些步骤。简单的例子是按钮点击,发布事件…
伪代码:
main() {
task1()
ThreadMain.handler.post(task2());
task3()
}
多线程+异步-并发和并行
非阻塞。
例如,当你需要在不阻塞的情况下在另一个线程上进行一些计算。伪代码:
main() {
task1()
new Thread(task2()).start();
//or
Future future = ExecutorService.submit(task2())
task3()
}
你可以使用阻塞方法get()或通过循环使用异步回调来使用Task 2的结果。
例如,在移动世界中,我们有UI/主线程,我们需要下载一些东西,我们有几个选择:
同步块-阻塞UI线程并等待下载完成。UI没有响应。 异步回调-创建一个新的线程,使用异步回调来更新UI(不可能从非UI线程访问UI)。回调地狱。 async coroutine[关于]-带有同步语法的异步任务。它允许将下载任务(挂起功能)与UI任务混合。
[iOS同步/异步],[Android同步/异步]
[并行vs并行]
举个简单的例子,
同步
想象一下,三个学生被要求在公路上进行接力赛。
第一个学生跑完指定的距离,停下来把接力棒传给第二个。没有人开始跑步。
1------>
2.
3.
当第二个学生拿起接力棒时,她开始跑指定的距离。
1.
2------>
3.
第二个学生解开了鞋带。现在她又停了下来,重新系上了领带。因此,2号的结束时间延长了,3号的开始时间推迟了。
1.
--2.--->
3.
这种模式一直持续到第三名从第二名手中接过接力棒并完成比赛。
异步
想象一下,10个人随机走在同一条路上。 他们当然不是在排队,只是随机地在路上不同的地方以不同的速度行走。
第二个人的鞋带被解开了。她停下来又把它扎了起来。
但没人等着她把头发扎起来。其他人都还在以同样的速度走着他们以前的路。
10--> 9-->
8--> 7--> 6-->
5--> 4-->
1--> 2. 3-->
我创建了一个动图来解释这一点,希望能有所帮助: 看,第3行是异步的,其他是同步的。 在行3之前的所有行都应该等到行完成它的工作,但因为行3是异步的,下一行(行4),不要等待行3,但行5应该等待行4完成它的工作,行6应该等待行5和7的6,因为行4,5,6,7不是异步的。
我认为这是一个有点迂回的解释,但它仍然澄清了使用现实生活中的例子。
小例子:
让我们假设播放音频包含三个步骤:
从硬盘中获取压缩的歌曲 解压音频。 播放未压缩的音频。
如果你的音频播放器为每首歌依次执行步骤1、2、3,那么它就是同步的。你必须等待一段时间才能听到这首歌,直到这首歌真正被提取和解压。
如果你的音频播放器独立执行第1、2、3步,那么它就是异步的。ie。 当播放音频1(步骤3)时,如果它并行地从硬盘中获取音频3(步骤1),并且并行地解压音频2。(第二步) 你最终会听到这首歌,而不需要等待太多的取回和解压。
同步是指调用方等待响应或完成,异步是指调用方继续执行并且稍后出现响应(如果适用的话)。
举个例子:
static void Main(string[] args)
{
Console.WriteLine("Before call");
doSomething();
Console.WriteLine("After call");
}
private static void doSomething()
{
Console.WriteLine("In call");
}
这将总是输出:
Before call
In call
After call
但如果我们要使doSomething()异步(有多种方式来做它),那么输出可以变成:
Before call
After call
In call
因为进行异步调用的方法将立即继续执行下一行代码。我之所以说“可能”,是因为异步操作无法保证执行顺序。它也可以作为原始文件执行,这取决于线程计时等。