关于同步、异步、阻塞、非阻塞的理解

对这四个概念,如果当初学习的时候没有从本质区别上做把握,日常编码中见过无数次,对它们的含义也就是只可意会不可言传;如果领悟得透彻,应该是可以表述以文字,也无需举例,就可以一语道破天机。

我是因为要去查查bio nio到底是什么含义,然后索引到了《Java BIO、NIO、AIO 学习》原链接:http://stevex.blog.51cto.com/4300375/1284437,反复琢磨了下,感觉这次可以计算机专业的角度做了一番领悟;感觉自己这次应该有所把握了。

文章原文的理解是:

先来个例子理解一下概念,以银行取款为例:

  • 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。

  • 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS(银行卡和密码),OS需要支持异步IO操作API)。

  • 阻塞 : ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回)。

  • 非阻塞 : 柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理,没到号你就不能去,你可以不断问大堂经理排到了没有,大堂经理如果说还没到你就不能去(使用非阻塞IO时,如果不能读写Java调用会马上返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成)。

ps:我当年学习的时候,咋没有这么认真,会做这样的类比与笔记。作者真是好学生,赞!


从对编程由浅入深的顺序讲,同步与异步这样的概念属于涉及到多线程时才碰到的高级概念,那么我先去谈谈对阻塞与非阻塞的两个概念的理解,由“阻塞”这个词,我的脑海立刻浮现出了交通阻塞的场景,早高峰打车上班时在某个路段滞留不动的焦急,其根本原因是因为道路不够宽敞且此时刻进来的车太多,从专业的角度讲,阻塞发生的根本原因是1.空间有限2.流量太大导致空间快速占满。再细化一点,空间属于计算机资源的范畴,叫做有限的资源被过载使用中,于是资源忙,而谁在使用资源呢,在交通领域使用资源的是开车的人,在计算领域里使用资源的是进程或者线程,而阻塞被定义为线程遇到“资源忙”而放弃了对CPU的控制权,直到资源不忙了才去争夺对CPU的控制权,这段时间线程就处于挂起的状态,而非阻塞正好相反,它被定义为不会因为“资源忙”而放弃对CPU的控制权,它继续占用CPU,做其他的事情;这就类比:遇堵车了,你这个人啥都不做了,那么你的人生就被定格在了阻塞这个状态,假如你发现堵车了立即转向做别的事情,之后不断地看看路是不是通了;路是一定会通的,但是选择不放弃CPU控制权的人却做了更多额外的工作。

总结如下:阻塞就是系统一说没资源就放弃对cpu的控制;而非阻塞是绝不轻易放弃对cpu的控制;很明显相同时间内,非阻塞的设计,使得线程在完成主业的同时,还做了很多副业。

对函数阻塞与非阻塞的设计里,分析其代码实现里都有关联一个资源这个东西在,于是才有资源忙这种情形的发生,而函数的设计者就是预想了函数调用者对待"资源忙"时的应该有两种截然不同的态度,你是干等着呢,还是边等边做事呢。

线程A去执行这种函数调用,不论是阻塞还是非阻塞,函数的返回结果都是在本线程里得到。在整个执行过程中,并不会有其他的线程来帮助分担一点什么。

为什么会有非阻塞的这样灭绝人性的函数调用,就是操作系统这个大boss就算没有资源给你,也希望你不要停止工作,就算让你忙东忙西,让你打杂也不会让你Sleep一下。让你一个人孤独、且繁忙!

操作系统这个大boss会让只压榨你一个人的所有的价值吗,它更残暴的做法是发明了异步,多线程时代的来临使得操作系统变本加厉尝试压榨一个团队的所有的价值。

计算机哲学解决高性能问题,无非就是会引入一个中间层,叫它中介也好,叫它代理也好,叫它工作者也好,总之原本一个任务如果分为三步指令都由一个线程从头到尾做完,现在大BOSS觉得你慢,就算提供非阻塞的机制还是觉得你慢,那么好就让你这个线程做你干的最快的那一步,并且专业做那一个指令;专业的线程做专业的指令,而其他的指令交给其他的线程去做,交给中间层去做,然后中间层做完之后来通知你。这就是异步。

这里的中间层就是抽象出一个解决你不能快速完成的指令的层次,它可以使操作系统本身系统级调用,或者是其他的线程。

在计算机的世界里,原来是也是专业的线程做专业的事情,然后靠任务合理的分发与结果反馈来实现更高的工作效率啊,高吞吐量。而如何建立这个分发与反馈机制,才是管理者的价值所在:先知人,后善用。怎么能容忍有才不任或不用则废的事情发生呢。

而同步是什么鬼?如果要做异步这样的设计,并且发挥多核的优势,其前提是把一个任务做合理的拆分成多个步骤,一步到位的工作方式演变成了多人协作各干一部分一起干完,再进一步演化为你所做的那个子任务还会有其他的跟你一样的牛逼的线程跟你做一样的事情;注意老板卓越的管理哲学的是怎么演变的:
第一阶段:阻塞(你忙直到没资源了你就休息一下)
第二阶段:非阻塞(你忙到没资源了我希望你干点别的事,不能闲着)
第三阶段:异步(你干这一步干的比别人好,就让你一个人专门干这一步,其他的步骤交给多个别人去干,干好了通知你,但你就不要奢望没资源了或许可以休息一会,你不是说你是专家吗,就爱干这吗,那永不停息吧)
第四阶段:同步(知道你忙,那么就安排一群和你一样的专家一起干一样的事情,但是要注意时序别搞乱了)

同步的问题产生,就是多线程并发执行相同的指令序列且牵涉到了操作相同的资源了,又是资源问题,这里的资源不仅是既有的如全局变量的这样的资源,还有可能是前一条指令执行完之后产生的资源。资源总是如此奇缺而各个专家级别平等,都要求说只有独占才能保证得到预期的结果。

总结:同步是对相同资源并行操作的时序约束,而异步是指令分解后把繁忙工作外包给第三者、通知反馈而自己专注高效的事情的机制。

异步的系统,总是伴随着分布系统设计的理念,与消息队列的这样的基本组件。

同步与异步相比,似乎在说明请一群专家按照时序商量来商量去的做事情,不如异步这种模型我直接把苦活外包给别人做,性价比要高。

毕竟一群专家,养不起啊。沟通也痛苦。

替代异步完成任务的第三者,往往就是系统本身,就是BOSS本身,只有BOSS才是最能调度资源与对资源的绝对控制权的,为什么不让BOSS去做呢。BOSS本该为人民服务,BOSS做得多,就意味着成本低,显然BOSS一人的价值往往是一个专家级别的员工的十倍吧。当然要想有更高的价值,就必须多个BOSS相互合作了,那就是所谓的分布式系统了。
想了这些之后,我才对下面这段话有了理解很明白;

----------------------------------------------------------------------


Java对BIO、NIO、AIO的支持

  • Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

  • Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

  • Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理,


BIO、NIO、AIO适用场景分析:

  • BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

  • NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

  • AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。


另外,I/O属于底层操作,需要操作系统支持,并发也需要操作系统的支持,所以性能方面不同操作系统差异会比较明显。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值