同步与异步语言
在过去的一年里,我从事 Java 和 Flex 方面的工作。在编写 Flex 代码时,我的大部分代码部分都因为它是异步的而被折腾了。它让我思考同步执行语言与异步执行语言的真正优点和缺点。
与其他人相比,他们在哪些方面更强,又在哪些方面落后?
In last 1 year I was working on Java and flex. While coding flex, most of my code parts went for a toss since its asynchronous. It made me to think about the real advantages and disadvantages of synchronous executing languages vs asynchronously executing ones.
What are the areas where they are stronger compared to other and what are the areas they falls?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
去年我大部分时间都在 Silverlight 中进行编码,这意味着我花了很多时间思考(并解决)您所描述的相同问题。
简而言之,正如其他人指出的那样,异步模型的真正优势在于它能够创建与现实世界良好互操作的强大系统。如果每次 Web 服务调用需要几秒钟返回时 UI 线程就会停止,那么没有人能够真正使用 Silverlight(或 Flash)应用程序。
最大的缺点是生成的代码很复杂并且难以排除故障。诸如错误处理之类的事情是 PITA,但我必须处理的最烦人的事情是协调多个异步调用的响应。比如说,如果您在调用 B 之前需要调用 A 中的信息,并且在调用 C 之前需要调用 B 中的信息(等等),则生成的代码看起来确实令人不快,并且容易受到各种奇怪的副作用的影响。有一些技术可以让所有这些东西工作,甚至相当干净,但如果你来自同步世界(就像我一样),这是一个重要的学习曲线。 (在我看来,当回调更加干净并且不易受到我所说的那种奇怪的副作用影响时,微软推送事件作为处理 WCF 调用的方式并没有帮助。)
(是的,其他人的说法是正确的,这不是一种异步语言,而是特定的框架需要以异步方式构建代码 - 但我明白你的意思。)
更新 2014.09.23 -
我已经做了很多工作自从我写了上面的答案(可能其他所有做过 Web 编码的人也一样)以来,我一直在使用各种异步框架,并且我想添加一些额外的随机注释:
如果您使用的是 C# 或F# 具有一流的异步支持,至少,一旦您了解了奇怪的
async
/await
模式,很多事情都会变得容易得多。能够轻松地循环异步调用,并用一个简单的try/catch
包装整个事情,如果您曾经不得不用旧的方式来做,那就太棒了。如果您使用的语言不具有一流的异步支持,请开始使用任何
promise
或future
或task
支持语言确实提供了(例如,JQuery 的$.Deferred()
或 Angular 的$q.defer()
)。这些比您通常得到的要干净得多,并且提供更好的结构异步代码对于编写可扩展的服务器端系统至关重要,使典型的 Web 服务器能够很好地扩展,它会开始耗尽线程,至少在这种情况下 它专用一个线程来处理传入的请求,如果该线程因等待长时间运行的同步调用完成而停止,则它完全无法帮助执行其他任何操作。更好的方法是使您的 Web 服务器代码异步,这样当您等待数据库调用返回时,该线程可以在数据库运行并执行数据库所做的任何操作时服务六个其他请求。此时,对于高度可扩展的系统,异步是唯一的选择。 (只需询问任何 Node 爱好者即可。)
I've spent most of the last year coding in Silverlight, which means I've spent a good deal of time thinking through (and fighting with) the same issues you're describing.
In brief, as other folks have pointed out, the real strength to the asynchronous model is its ability to create robust systems that interoperate well with the real world. Nobody could realistically use a Silverlight (or Flash) application if the UI thread came to a halt every time it took a few seconds for a web service call to return.
The biggest downside is that it the resulting code is complex and difficult to troubleshoot. Things like error handling are a PITA, but the most annoying stuff I've had to deal with is coordinating responses from multiple asynchronous calls. If, say, you need information from call A before making call B, and you need information from call B before making call C (and so forth), the resulting code looks really unpleasant, and is susceptible to all sorts of weird side-effects. There are techniques for making all this stuff work, and even reasonably clean, but if you're coming from the synchronous world (as I was), it's a significant learning curve. (And it doesn't help that Microsoft pushes events as the way to deal with WCF calls when callbacks, in my opinion, are much cleaner and less susceptible to the sort of weird side-effects I was talking about.)
(And yes, other folks are correct in saying that it's not the language that's asynchronous so much as that particular frameworks require constructing your code in an asynchronous manner -- but I get what you mean.)
Update 2014.09.23 -
I've done a lot more work with a variety of asynchronous frameworks since I wrote the answer above (as has probably everybody else who's done any web coding), and thought I'd add a few additional random notes:
If you're using a language like C# or F# that has first-class asynchronous support, a lot of this gets a whole lot easier, at least, once you wrap your head around the weird
async
/await
patterns. Being able to loop easily around asynchronous calls, and wrap the whole thing with a simpletry/catch
, is amazing if you've ever had to do it the old way.If you're not using a language with first-class async support, start using whatever
promise
orfuture
ortask
support that the language does provide (e.g., JQuery's$.Deferred()
, or Angular's$q.defer()
. Those are a lot cleaner and provide better structure than what you typically get with callbacks.Asynchronous code is critical for writing scalable server-side systems. One of the biggest issues with making a typical web server scale well is that it starts running out of threads, at least, it does if it dedicates a thread to reach incoming request. If that thread stalls, because it's waiting for a long-running synchronous call to finish, it's completely unavailable for helping out with anything else. Much better is to make your web server code async, so that when you're waiting on a DB call to return, that thread can go service half a dozen other requests while the DB is going and doing whatever DB's do. At this point, for highly scalable systems, async is the only game in town. (Just ask any Node aficionado.)
(抛开语义层面的讨论,即“同步/异步语言”)
基于“语言”(无论它是什么)构建的“框架”应该能够处理这种情况(同步/异步程序流),以便有用(阅读:$明智)。
异步惯用语适用于各种规模。
在大规模上,异步技术有助于构建可靠的系统,因为现实世界本质上是异步的。换句话说,人们需要以“异步思维”来思考,以应对现实生活中的情况,例如失败、损失、延迟等。
即使在较小的规模上(例如 GUI 应用程序),事件(例如“鼠标单击”)也往往会发生。是“异步”的。当然,它们在某个时刻被“序列化”(以便可由运行某些软件的应用程序处理),但它不会改变事件(可能)发生的事实
关于相关程序的流程,“异步”。
(Leaving aside the semantics level discussion i.e. "sync/async language")
A "framework" built on a "language" (whatever it is) should be able to handle such cases (sync/async programme flow) in order to be useful (read: $ wise).
Asynchronous idioms are appropriate at every scale.
At large scale, asynchronous techniques help build reliable systems because the real world is anyhow asynchronous in nature. In other words, one needs to think in "asynchronous thoughts" to cope with real-life situations such as failures, losses, delays etc.
Even on a smaller scale (e.g. GUI application), events (such as "mouse clicks") tend to be "asynchronous". Of course they are "serialized" at some point (in order to be processable by an application running some software) but it doesn't change the fact that events (probably) occurred
"asynchronously" with regards to the flow of the programme in question.
我认为这不是语言的问题,而是框架的问题。
反例:
当用 C(一种“同步”语言,如果有的话)编写“经典 Mac”(MacOS 9 及之前版本)应用程序时,您没有抢占式多线程,因此所有可能阻塞的系统调用都有一个异步对应,您可以在其中使用包括回调函数的参数填充数据块。然后,您执行系统调用(将立即返回),并且您的回调将被异步调用(在所谓的“中断级别”中)。回调执行另一个异步系统调用,创建一个与主线程异步运行的长后台线程,这种情况并不罕见。
I think it's not about the language, but about the framework.
Counter-case in point:
When writing 'Classic Mac' (MacOS 9 and before) applications in C (a 'synchronous' language if there ever was one), you don't have preemptive multithreading, so all potentially blocking system calls have an async counterpart, where you fill a block of data with parameters including a callback function. Then you do the system call (which would return immediately), and your callback would be called asynchronously (in what's called 'interrupt level'). It wasn't uncommon that a callback would do another async system call, creating a long background thread that ran asynchronously with the main one.