Java网络编程------IO模型的同步/异步/阻塞/非阻塞(1)

一、同步/异步/阻塞/非阻塞

1、同步和异步

同步,指的是协同步调。协同的结果就是,多个事物不能同时进行,必须一个一个来。一个事物在进行时,其他的事物在干嘛呢?

严格来讲这个并没有要求,但一般都是处于一种“等待”的状态,因为通常后面事物的正常进行都需要依赖前面事物的结果或前面事物正在使用的资源。 因此,可以认为,同步更希望关注的是从宏观整体来看,多个事物是一种逐个逐个的串行化关系,绝对不会出现交叉的情况。 所以,自然也不太会去关注某个瞬间某个具体事物是处于一个什么状态。

比如排队购买火车票:其实售票大厅更在意的是旅客一个一个的到窗口去买票,因为一次只能卖一张票。即使大家一窝蜂的都围上去,还是一次只能卖一张票,何必呢?采用排队这种形式就很好,至于每个旅客排队时的状态,是看手机呀还是说话呀,根本不用去在意。

除了上述由于资源导致的同步外,还存在一种逻辑上的先后顺序导致的同步。 比如,先更新代码,然后再编译,接着再打包。这些操作由于后一步要使用上一步的结果,所以只能按照这种顺序一个一个的执行。

关于同步还需要注意两点:一是范围,并不需要在全局范围内都去同步,只需要在某些关键的点执行同步即可。二是粒度,并不是只有大粒度的事物才有同步,小粒度的事物也有同步。只不过小粒度的事物同步通常是天然支持的,而大粒度的事物同步往往需要手工处理。 比如两个线程的同步就需要手工处理,但一个线程里的两个语句天然就是同步的。同步调用模型
异步,就是步调各异。既然是各异,那就是都不相同。所以结果就是: 多个事物可以你进行你的、我进行我的,谁都不用管谁,所有的事物都在同时进行中。

异步调用模型

2、阻塞和非阻塞

阻塞,指的是阻碍堵塞。它的本意可以理解为由于遇到了障碍而造成的动弹不得。

非阻塞,自然是和阻塞相对,可以理解为由于没有遇到障碍而继续畅通无阻。

因此阻塞关注的是不能动,非阻塞关注的是可以动。不能动的结果就是只能等待,可以动的结果就是继续前行。 因此和阻塞搭配的词一定是等待,和非阻塞搭配的词一定是进行。回到程序里,阻塞同样意味着停下来等待,非阻塞表明可以继续向下执行。

阻塞的真正含义是你关心的事物由于某些原因无法继续进行,因此让你等待。但没必要干等,你可以做一些其它无关的事物,因为这并不影响你对相关事物的等待。比如在堵车时,你可以干等。也可以玩手机、和别人聊天,或者打牌、甚至先去吃饭都行。因为这些事物并不影响你对堵车的等待。不过你的车必须呆在原地。

在计算机里,是没有人这么灵活的,一般在阻塞时,选在干等,因为这最容易实现,只需要挂起线程,让出CPU即可。在条件满足时,会重新调度该线程。

3、同步、异步和阻塞、非阻塞组合

同步异步关注的是能不能同时工作,阻塞和非阻塞关注的是等待时能不能干其他的事情。所以我们可以得到以下几种组合:

类型特点程序中
同步阻塞不能同时工作,等待时不能做其他工作相当于一个线程在等待
同步非阻塞不能同时工作,等待时能做其他工作相当于一个线程在正常运行
异步阻塞能同时工作,等待时不能做其他工作相当于多个线程都在等待
异步非阻塞能同时工作,等待时能做其他工作相当于多个线程都在正常运行

二、IO

1、I/O

IO指的就是读入/写出数据的过程,和等待读入/写出数据的过程。一旦拿到数据后就变成了数据操作了,就不是IO了。 拿网络IO来说,等待的过程就是数据从网络到网卡再到内核空间。读写的过程就是内核空间和用户空间的相互拷贝。

所以IO就包括两个过程,一个是等待数据的过程,一个是读写(拷贝)数据的过程。而且还要明白,一定不能包括操作数据的过程。

2、阻塞IO和非阻塞IO

应用程序都是运行在用户空间的,所以它们能操作的数据也都在用户空间。按照这样子来理解,只要数据没有到达用户空间,用户线程就操作不了。如果此时用户线程已经参与,那它一定会被阻塞在IO上。这就是常说的阻塞IO。用户线程被阻塞在等待数据上或拷贝数据上。

非阻塞IO就是用户线程不参与以上两个过程,即数据已经拷贝到用户空间后,才去通知用户线程,一上来就可以直接操作数据了。用户线程没有因为IO的事情出现阻塞,这就是常说的非阻塞IO。

3、同步IO和同步阻塞IO

同步IO是指发起IO请求后,必须拿到IO的数据才可以继续执行。 按照程序的表现形式又分为两种: 在等待数据的过程中,和拷贝数据的过程中,线程都在阻塞,这就是同步阻塞IO。在等待数据的过程中,线程采用死循环式轮询,在拷贝数据的过程中,线程在阻塞,这其实还是同步阻塞IO。

非阻塞IO意味着发起IO请求后,可以继续往下执行。说明后续执行不依赖于IO数据,所以它肯定不是同步的。 因此,在IO上,同步和非阻塞是互斥的,所以不存在同步非阻塞IO。但同步非阻塞是存在的,那不叫IO,叫操作数据了。

4、异步IO和异步阻塞/非阻塞IO

异步IO是指发起IO请求后,不用拿到IO的数据就可以继续执行。

用户线程的继续执行,和操作系统准备IO数据的过程是同时进行的,因此才叫做异步IO。 按照IO数据的两个过程,又可以分为两种:

  1. 在等待数据的过程中,用户线程继续执行,在拷贝数据的过程中,线程在阻塞,这就是异步阻塞IO。
  2. 在等待数据的过程中,和拷贝数据的过程中,用户线程都在继续执行,这就是异步非阻塞IO。

第一种情况是,用户线程没有参与数据等待的过程,所以它是异步的。但用户线程参与了数据拷贝的过程,所以它又是阻塞的。合起来就是异步阻塞IO。

第二种情况是,用户线程既没有参与等待过程也没有参与拷贝过程,所以它是异步的。当它接到通知时,数据已经准备好了,它没有因为IO数据而阻塞过,所以它又是非阻塞的。合起来就是异步非阻塞IO。

5、IO Block

考虑下面两种情况:

  1. 用系统调用read从socket里读取一段数据
  2. 用系统调用read从一个磁盘文件读取一段数据到内存

如果你的直觉告诉你,这两种都算“Block”,那么很遗憾,你的理解与Linux不同。Linux认为:

  1. 对于第一种情况,算作block,因为Linux无法知道网络上对方是否会发数据。如果没数据发过来,对于调用read的程序来说,就只能“等”。
  2. 对于第二种情况,不算做block。

所谓“Block”是指操作系统可以预见这个Block会发生才会主动Block。例如当读取TCP连接的数据时,如果发现Socket buffer里没有数据就可以确定定对方还没有发过来,于是Block;而对于普通磁盘文件的读写,也许磁盘运作期间会抖动,会短暂暂停,但是操作系统无法预见这种情况,只能视作不会Block,照样执行。基于这个基本的设定,在讨论IO时,一定要严格区分网络IO和磁盘文件IO。

本博客引用文章:
圈T社区- - -迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的最清楚的好文章

下一篇:Java网络编程------IO模型BIO/NIO(2)

我们怕的不是能力不足,而是怕自己能力太强,我们自问,我凭什么天赋异禀,事实上,你凭什么不能天赋异禀,人生在世的目的就是发挥上天赐给的天赋,当我们发光发热时,也让别人有了见贤思齐的勇气。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豢龙先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值