2011-03-12 119 views
18

据我所知,同步和异步操作之间的主要区别。即write()read() vs async_write()async_read()是前者,直到操作完成后才返回 - 或错误 - 和最后一个,立即返回。需要关于同步和异步操作的一些说明

由于异步操作由io_service.run()控制,直到受控操作完成才完成。在我看来,在连续的操作中所涉及的与协议,如POP3 TCP/IP连接,其中操作的顺序,如:

C: <connect> 
S: Ok. 
C: User... 
S: Ok. 
C: Password 
S: Ok. 
C: Command 
S: answer 
C: Command 
S: answer 
... 
C: bye 
S: <close> 

同步/异步运营商之间的差别并不太大感。

当然,在这两个操作中,程序流程总会有一定的风险 - 在某些情况下 - 使用定时器 - ,但我想知道更多关于此问题的授权意见。

我必须承认,这个问题是相当不明确的,但我想听听什么时候使用其中一个的建议。在使用MS Visual Studio进行调试时,我遇到了一些问题,这些问题涉及到我正在使用的POP3客户端中的异步SSL操作,有时候认为在这种情况下使用异步也许是个坏主意。

+4

+1甚至没有接近不明确的问题。异步编程很难,不要羞于对它提出疑问。 – 2011-03-13 14:11:20

回答

3

我想同步/异步的选择是非常特定于应用程序的。我同意异步范例可以使代码和调试更加复杂,但它确实有其好处。

为了说明,我们使用异步IO从同步IO切换到boost asio的主要原因在于,在我们的应用程序中,阻止IO仅仅是一种选择,我们有一个多媒体流媒体服务器,客户编码后。问题在于网络问题导致整个捕获 - 编码 - 交付流水线被有效阻塞(例如,如果与单个客户端的连接失败)。总结一下,在我的(有关异步IO的经验)中,它可以用于在等待IO完成时需要完成其他工作的情况(例如为其他客户端提供服务等) 。在系统或场景中,如果您必须等待IO的结果继续,那么仅使用同步IO就简单多了。

在双工通信系统中(例如更复杂的协议,例如SIP和RTSP,客户端和服务器都可以发送请求),这也是有意义的。自从我处理POP以来,这已经有一段时间了,但在您的示例中进行了简单交换之后,异步IO可能会被视为过度消耗。只有当我确定同步IO不足以满足我的要求时,我才会切换到异步IO。

WRT到boost asio文档,我发现最好的方法是完成这个例子。此外,您可能想要查看的链接是http://en.highscore.de/cpp/boost/index.html它对增强asio有非常好的一章。另外Chris Kohlhoff's (author of asio) blog有一些非常优秀的文章值得一试。

+0

感谢您的意见。你的话对我来说是有道理的,而且到目前为止还没有人知道这本高分榜。 – 2011-03-12 21:14:58

31

Boost.Asio documentation对解释这两个概念真的很出色。作为Ralf mentioned,克里斯还有一个很棒的博客,描述异步概念。解释超时工作方式的parking meter示例与bind illustrated示例一样特别有趣。

首先,考虑同步连接操作:

synchronous connect

控制流程相当简单在这里,你的程序调用API的一些(1)连接套接字。 API使用I/O服务(2)在操作系统(3)中执行操作。一旦此操作完成(4和5),控制器会立即返回到您的程序(6),并显示成功或失败的指示。

中类似的异步操作具有完全不同的控制流程:

asynchronous connect

在这里,你的应用发起使用相同的I/O服务(2)的操作(1),但该控制流是倒。操作完成后,I/O服务会通过完成处理程序通知您的程序。步骤3到操作完成之间的时间完全包含在同步案例的连接操作中。

对于大多数程序员来说,您可以看到同步案例自然更容易掌握,因为它代表了传统的控制流范式。异步操作使用的反向控制流很难理解,它经常会迫使你的程序将操作分解为逻辑移位的方法starthandle。但是,一旦你对这个控制流程有了基本的了解,你就会意识到这个概念真的有多强大。异步编程的一些优点是:

  • 将线程从并发中分离出来。执行长时间运行的操作,对于同步情况,您通常会创建单独的线程来处理操作,以防止应用程序的GUI无响应。这个概念在小范围内运行良好,但很快就会在一些线程中崩溃。

  • 性能提高。线程每连接设计根本不会缩放。请参阅C10K problem

  • 构图(或链接)。更高级别的操作可以由多个完成处理程序组成。考虑传输JPEG图像,该协议可能规定前40个字节包括描述图像大小,形状或其他信息的标题。发送此标头的第一个完成处理程序可以启动第二个操作来发送图像数据。更高级别的操作sendImage()不需要知道或关心用于实现数据传输的方法链接。

  • 超时和取消能力。有特定于平台的方式来超时长时间运行(例如:SO_RCVTIMEOSO_SNDTIMEO)。使用异步操作可以使用deadline_timer取消所有支持的平台上的长时间运行操作。


当然,在这两个操作有 永诺的程序流程 无限期停止一些 circunstance -there使用 timers-的风险,但我想知道一些 更多关于此 事宜的授权意见。

我个人使用Asio的经验源于可扩展性方面。编写supercomputers的软件需要在处理有限的资源(如内存,线程,套接字等)时进行相当的处理。使用每个线程连接200万个同时进行的操作是一种在到达时已死亡的设计。

+2

尽管使用它的时间已经过去,互联网仍然不时地对我“保持一丝”魔力“。在这种情况下,有免费的好老师的奇迹。谢谢。 – 2011-03-13 18:59:46

+0

我总是发现难以理解短语“倒转控制流”。所以你可以在这个上下文中详细说明“倒置”这个词*“你的应用程序使用相同的I/O服务(2)**启动操作(1),但是控制流被反转**。尽管我非常了解控制流,但我无法将“反转”一词与异步情况中发生的情况联系起来。对我而言,感觉就像选择一个随机单词来给控制流*一个名字或标签。 – Nawaz 2016-08-24 03:55:47

+0

**反向控制流**表示框架或库(此答案中的Asio)回调到程序中,这些是异步操作完成时的回调。与程序直接调用框架或库的典型过程编程相比,ex:同步send()操作在完成时返回控制权。 – 2016-08-29 04:59:40

0

一个简单的回答是:(引自here几乎不做修改)

同步客户一切都发生在串行。如果你发送一个命令,它会排队在前一个命令后面,直到它们完成。通常是单线程应用程序。

在ASync中,所有事情都同时发生。通常会同时承担多项任务的多线程应用程序。

+2

Javascript是单线程和异步...和美妙的。我不认为异步连接到多线程 – 2016-01-11 12:13:37

+0

向下投票:我不认为这是正确的。处理多个网络连接的一种方法是为每个连接建立一个线程或进程,并且每个连接都在自己的线程/进程中运行,所有的I/O都是同步的。在异步I/O设计中,您可以拥有任意数量的线程或进程,即使是单个进程也可以处理多个连接。事实上,我猜测发明异步I/O机制的一个主要动机是摆脱编写(过度)多线程代码的需求,这些代码在某些平台上带来了自己的可伸缩性问题。 – FooF 2016-03-28 14:01:48