异步与多线程-有区别吗?


133

异步调用是否总是创建一个新线程?两者有什么区别?

异步调用是否总是创建或使用新线程?

维基百科说

在计算机编程中,异步事件是独立于主程序流程而发生的事件。异步动作是在非阻塞方案中执行的动作,允许主程序流继续进行处理。

我知道异步调用可以在单线程上完成吗?这怎么可能?



1
JavaScript没有线程,但是有异步方法调用。
Ajedi32

1
在一个进程管理多个子进程的任何系统中,控制进程都可以提供子进程的异步操作。对于JavaScript,浏览器将提供计算流。当某个函数进行异步调用时,浏览器可以存储该函数的上下文。现在,同一个浏览器线程可以更改上下文以继续执行另一个功能。在传统的多线程程序中,一个线程执行一个功能块以允许另一个线程运行不同的功能。每个线程同步执行自己的功能。
迈克”

Answers:


82

这个问题太笼统了,无法回答。

在一般情况下,异步调用不一定会创建新线程。这是实现它的一种方法,而预先存在的线程池或外部进程是其他方法。它在很大程度上取决于语言,对象模型(如果有)和运行时环境。

异步只是意味着调用线程不坐下来等待响应,异步活动也不会在调用线程中发生。

除此之外,您将需要更加具体。


7
因此,我基本上是这样说的:多线程==使用多个线程可以为处理器密集型任务提供处理上的好处,这些任务[理想地]可以从多个处理器中受益,并且可以在异步情况下受益。异步==一个完成任务的进程,而调用该进程的状态不必等待它完成。(可能不必使用多个线程来执行此操作,即其他硬件组件可能要负责)。
埃文·塞维

6
@Michael-您能举例说明一下如何在单个线程中进行异步编程吗?
Kumar Vaibhav

7
@KumarVaibhav-最常见的示例是单个线程处理队列(例如Windows消息队列)中的项目时。如果程序习惯于将项目发送到自己的队列中(一种常见的模式),那么发送项目的代码段就不会等待操作完成,而只是返回。主循环将在适当时候处理该操作。
迈克尔·科恩

3
代码的编写方式和执行方式可能有所不同。例如,在C#中,我可以有一个启动异步任务的方法,我的方法是完全异步的,并且可以做其他事情而无需等待任务完成。但是,CLR也可以决定内联我的任务并同步执行它。
迈克,

哪个线程执行等待的任务?标有a-sync的方法将同步执行,直到到达await关键字为止,这时哪个线程执行此可等待任务?

102

每当需要异步进行的操作不需要CPU进行工作时,就可以在不产生另一个线程的情况下完成该操作。例如,如果异步操作是I / O,则CPU不必等待I / O完成。它只需要开始操作,然后可以在I / O硬件(磁盘控制器,网络接口等)执行I / O工作时继续进行其他工作。硬件通过中断CPU来通知CPU完成时间,然后OS将事件传递给您的应用程序。

通常,更高级别的抽象和API不会公开来自操作系统和基础硬件的基础异步API。在这种情况下,即使生成的线程只是在等待I / O操作,通常也更容易创建线程来执行异步操作。

如果异步操作需要CPU完成工作,那么通常该操作必须在另一个线程中进行才能真正实现异步。即使那样,如果存在多个执行单元,它实际上也将是异步的。


1
很好的解释,谢谢;但我在这里有一个问题。您提到“例如,如果异步操作是I / O,则CPU不必等待I / O完成。它只需要启动操作即可”。我的问题是程序是单线程的,并且在代码行3中说,您调用一个I / O操作,然后如何在不等待I / O操作完成的情况下在第3行中启动该操作并执行第4行?对于我来说,我必须把代码中的第3行中一个新的线程来实现4号线,而不必等待I / O操作完成后执行[Java的PGM的角度。
蜘蛛侠

1
原因是,尽管CPU不必等待,但CPU将等待I / O操作完成...我相信您的第二段就是我查询的答案。在这种情况下,我需要得出结论,在Java中,异步调用需要在不同的线程中执行。如果我错了,请指正我,或者如果我必须发布新的SO qn,请告诉我
Spiderman

@spiderman某些语言(例如Node.js)具有异步编程模型。语言和运行时提供了内置功能,即使在IO操作完成之前,也允许在同一线程中执行第4行。这是通过第3行提供的,该回调提供了当IO完成时运行时将调用的回调。
jrahhali

@spiderman也许...操作系统的Async函数只是返回false或直接返回某些内容。
Byeongin Yoon '18

18

不,异步调用并不总是涉及线程。

它们通常确实会启动某种操作,该操作与调用方并行进行。但是该操作可能由另一个进程,操作系统,其他硬件(如磁盘控制器),网络上的其他计算机或人来处理。线程并不是并行完成任务的唯一方法。



12

多线程是指在同一进程中发生的多个操作。而异步编程则跨进程进行。例如,如果我的操作调用了Web服务,则线程不必等到Web服务返回。在这里,我们使用异步编程,该编程允许线程不等待另一台计算机上的进程完成。当它开始从Web服务获取响应时,它可以中断主线程,以表明Web服务已完成对请求的处理。现在,主线程可以处理结果。


我有点不同意。我编写了一个单线程HTTP服务器,该服务器使用异步IO完成来处理多个同时请求。异步不需要事情在多个执行路径上发生,它只意味着多个计算流可以重叠。另一种看待它的方法是,在一个单线程OS上,我可以让2个进程“同时”运行。从每个进程的角度来看,它们都是同步运行的。但是,从OS的角度来看,它是异步运行的。
迈克

11

由于非抢占时间(版本2.13、3.0、3.1等)使用消息循环(在支持实线程之前),Windows始终具有异步处理。因此,要回答您的问题,不,没有必要创建线程来执行异步处理。


@dmckee-有趣的是,不同的系统如何以相似的方式发展。
奥塔维奥·德西奥

8

异步呼叫甚至不需要与调用该呼叫的系统/设备在同一系统/设备上进行。因此,如果问题是,异步调用在当前进程中是否需要线程,答案是否定的。但是,在处理异步请求的某处必须有一个执行线程。

执行线程是一个模糊的术语。在早期的Macintosh和Windows OS之类的协作式任务系统中,执行线程可能只是使请求运行另一个堆栈,指令指针等的同一进程。但是,当人们通常谈论异步调用时,它们通常表示由另一个线程(如果在进程内(即,在同一进程内))处理,或者由另一个进程(在进程间)进行处理。

请注意,进程间(或进程间)通信(IPC)通常被概括为包括进程内通信,因为锁定和同步数据的技术通常是相同的,而与执行各个执行线程所处的进程无关。


7

有些系统允许您使用回调的某些功能来利用内核中的并发性。对于一个相当模糊的实例,在Mac System 6-8的无抢占式多任务处理时代,异步IO回调用于实现无阻塞Internet服务器。

这样,您就可以在程序中“并发”执行并发执行流,而无需这样的线程。


5

异步只是意味着您不会阻塞程序等待某些东西(函数调用,设备等)完成。它可以在单独的线程中实现,但是通常使用专用线程执行同步任务并通过某种事件系统进行通信,从而实现类似异步的行为。

有单线程异步程序的示例。就像是:

...do something
...send some async request
while (not done)
    ...do something else
    ...do async check for results

2

异步调用的性质是,如果您希望应用程序在调用过程中继续运行,则需要生成一个新线程,或者至少要利用您自己创建的另一个线程来专门用于以下目的:处理异步回调。

有时,根据情况,您可能想调用一个异步方法,但使它在用户看来是同步的(即阻塞,直到异步方法已完成该信号为止)。这可以通过Win32 API(例如WaitForSingleObject)来实现。


在某些系统上是这样,但不是全部。Unix不需要您生成或利用另一个线程,除非您将另一个线程称为内核,我认为这是查看它的一种方式。
克雷格S

在Windows上也不是这样。例如,重叠的I / O是异步的。
杰森·奥伦多夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.