做者:严肃
连接:https://www.zhihu.com/question/19732473/answer/20851256
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
“阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解,提供一个从分布式系统角度的回答。
1.同步与异步
同步和异步关注的是消息通讯机制 (synchronous communication/ asynchronous communication)
所谓同步,就是在发出一个*调用*时,在没有获得结果以前,该*调用*就不返回。可是一旦调用返回,就获得返回值了。
换句话说,就是由*调用者*主动等待这个*调用*的结果。
而异步则是相反,*调用*在发出以后,这个调用就直接返回了,因此没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会马上获得结果。而是在*调用*发出后,*被调用者*经过状态、通知来通知调用者,或经过回调函数处理这个调用。
典型的异步编程模型好比Node.js
举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,若是是同步通讯机制,书店老板会说,你稍等,”我查一下",而后开始查啊查,等查好了(多是5秒,也多是一天)告诉你结果(返回结果)。
而异步通讯机制,书店老板直接告诉你我查一下啊,查好了打电话给你,而后直接挂电话了(不返回结果)。而后查好了,他会主动打电话给你。在这里老板经过“回电”这种方式来回调。
2. 阻塞与非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回以前,当前线程会被挂起。调用线程只有在获得结果以后才会返回。
非阻塞调用指在不能马上获得结果以前,该调用不会阻塞当前线程。
仍是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你若是是阻塞式调用,你会一直把本身“挂起”,直到获得这本书有没有的结果,若是是非阻塞式调用,你无论老板有没有告诉你,你本身先一边去玩了, 固然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板经过什么方式回答你结果无关。
老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张以为本身有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张仍是以为本身有点傻,因而变高端了,买了把会响笛的那种水壶。水开以后,能大声发出嘀~~~~的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张以为这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响以前再也不去看它了,响了再去拿壶。(异步非阻塞)
老张以为本身聪明了。
所谓同步异步,只是对于水壶而言。
普通水壶,同步;响水壶,异步。
虽然都能干活,但响水壶能够在本身完工以后,提示老张水开了。这是普通水壶所不能及的。
同步只能让调用者去轮询本身(状况2中),形成老张效率的低下。
所谓阻塞非阻塞,仅仅对于老张而言。
立等的老张,阻塞;看电视的老张,非阻塞。
状况1和状况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。因此通常异步是配合非阻塞使用的,这样才能发挥异步的效用。
做者:愚抄
连接:https://www.zhihu.com/question/19732473/answer/23434554
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
做者:厂长
连接:https://www.zhihu.com/question/33578075/answer/56951771
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
译文以下:
若是你去年注意过技术方面的新闻,我敢说你至少看到node.js不下一两次。那么问题来了“node.js是什么?”。有些人没准会告诉你“这是一种经过JavaScript语言开发web服务端的东西”。若是这种晦涩解释还没把你搞晕,你没准会接着问:“为何咱们要用node.js?”,别人通常会告诉你:node.js有非阻塞,事件驱动I/O等特性,从而让高并发(high concurrency)在的轮询(Polling)和comet构建的应用中成为可能。
当你看完这些解释以为跟看天书同样的时候,你估计也懒得继续问了。不过没事。我这篇文章就是在避开高端术语的同时,帮助你你理解node.js的。
浏览器给网站发请求的过程一直没怎么变过。当浏览器给网站发了请求。服务器收到了请求,而后开始搜寻被请求的资源。若是有须要,服务器还会查询一下数据库,最后把响应结果传回浏览器。不过,在传统的web服务器中(好比Apache),每个请求都会让服务器建立一个新的进程来处理这个请求。
后来有了Ajax。有了Ajax,咱们就不用每次都请求一个完整的新页面了,取而代之的是,每次只请求须要的部分页面信息就能够了。这显然是一个进步。可是好比你要建一个FriendFeed这样的社交网站(相似人人网那样的刷朋友新鲜事的网站),你的好友会随时的推送新的状态,而后你的新鲜事会实时自动刷新。要达成这个需求,咱们须要让用户一直与服务器保持一个有效链接。目前最简单的实现方法,就是让用户和服务器之间保持长轮询(long polling)。
HTTP请求不是持续的链接,你请求一次,服务器响应一次,而后就完了。长轮训是一种利用HTTP模拟持续链接的技巧。具体来讲,只要页面载入了,无论你需不须要服务器给你响应信息,你都会给服务器发一个Ajax请求。这个请求不一样于通常的Ajax请求,服务器不会直接给你返回信息,而是它要等着,直到服务器以为该给你发信息了,它才会响应。好比,你的好友发了一条新鲜事,服务器就会把这个新鲜事当作响应发给你的浏览器,而后你的浏览器就刷新页面了。浏览器收到响应刷新完以后,再发送一条新的请求给服务器,这个请求依然不会当即被响应。因而就开始重复以上步骤。利用这个方法,可让浏览器始终保持等待响应的状态。虽然以上过程依然只有非持续的Http参与,可是咱们模拟出了一个看似持续的链接状态
咱们再看传统的服务器(好比Apache)。每次一个新用户连到你的网站上,你的服务器就得开一个链接。每一个链接都须要占一个进程,这些进程大部分时间都是闲着的(好比等着你好友发新鲜事,等好友发完才给用户响应信息。或者等着数据库返回查询结果什么的)。虽然这些进程闲着,可是照样占用内存。这意味着,若是用户链接数的增加到必定规模,你服务器没准就要耗光内存直接瘫了。
这种状况怎么解决?解决方法就是刚才上边说的:非阻塞和事件驱动。这些概念在咱们谈的这个情景里面其实没那么难理解。你把非阻塞的服务器想象成一个loop循环,这个loop会一直跑下去。一个新请求来了,这个loop就接了这个请求,把这个请求传给其余的进程(好比传给一个搞数据库查询的进程),而后响应一个回调(callback)。完事了这loop就接着跑,接其余的请求。这样下来。服务器就不会像以前那样傻等着数据库返回结果了。
若是数据库把结果返回来了,loop就把结果传回用户的浏览器,接着继续跑。在这种方式下,你的服务器的进程就不会闲着等着。从而在理论上说,同一时刻的数据库查询数量,以及用户的请求数量就没有限制了。服务器只在用户那边有事件发生的时候才响应,这就是事件驱动。
FriendFeed是用基于Python的非阻塞框架Tornado (知乎也用了这个框架) 来实现上面说的新鲜事功能的。不过,Node.js就比前者更妙了。Node.js的应用是经过javascript开发的,而后直接在Google的变态V8引擎上跑。用了Node.js,你就不用担忧用户端的请求会在服务器里跑了一段可以形成阻塞的代码了。由于javascript自己就是事件驱动的脚本语言。你回想一下,在给前端写javascript的时候,更多时候你都是在搞事件处理和回调函数。javascript自己就是给事件处理量身定制的语言。
Node.js仍是处于初期阶段。若是你想开发一个基于Node.js的应用,你应该会须要写一些很底层代码。可是下一代浏览器很快就要采用WebSocket技术了,从而长轮询也会消失。在Web开发里,Node.js这种类型的技术只会变得愈来愈重要。
以上