美文网首页
Java IO 学习(一)同步/异步/阻塞/非阻塞

Java IO 学习(一)同步/异步/阻塞/非阻塞

作者: taj3991 | 来源:发表于2020-02-21 16:09 被阅读0次

关于IO,同步/异步/阻塞/非阻塞,这几个关键词是经常听到的,譬如:
“Java oio是阻塞的,nio是非阻塞的”
“NodeJS的IO是异步的”
但是这些东西听多了就容易迷糊,比方说同步是否就是阻塞,异步是否就是非阻塞呢?

先给出结论:

  1. 异步/同步与阻塞/非阻塞之间没有必然的联系
  2. 同步IO可以是阻塞,也可以是非阻塞的
  3. 异步IO就是异步IO,它一定是非阻塞的,不存在异步阻塞IO这个说法

POSIX对同步/异步的定义如下,这两句话非常关键

  • A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
  • An asynchronous I/O operation does not cause the requesting process to be blocked;

再给出权威文档:《UNIX网络编程:卷一》的第六章

书中列出了如下五种IO模型:

  • 阻塞式I/O;

  • 非阻塞式I/O;

  • I/O复用(select,poll,epoll...);

  • 信号驱动式I/O(SIGIO);

  • 异步I/O(POSIX的aio_系列函数);

1. 阻塞式IO

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
  struct sockaddr *src_addr, socklen_t *addrlen);

在默认情况下,recvfrom方法会被阻塞,直到从指定的socket上收到数据才会返回,返回时,buf中已经填充好了数据.

阻塞的过程实际上可以分割成两段:等待kernel准备好从网络上接收到的数据报 + 等待收到的报文被从kernel复制到buf中.

只有在这两个过程全部完成后,recvfrom方法才会返回。

这就是阻塞式IO模型

2. 非阻塞式IO

还是上面的recvfrom方法,如果将其设置为非阻塞模式(flag与MSG_DONTWAIT异或),情况就会有所不同了:

在内核没有准备好数据报时,调用recvfrom方法会立即返回异常码(EWOULDBLOCK或者EAGAIN)(这一段是非阻塞的!)

如果内核已经准备好数据,调用recvfrom方法则会在数据报被从kernel拷贝到buf中后返回(这一段是同步的!)

也就是说,阻塞与非阻塞式IO的主要区别在于等待数据报准备好的第一阶段, 至于将数据从kernel拷贝到buf中的过程,两者都是同步的。

但是个人觉得非阻塞式IO可能并不好用,因为在轮询一个socket是否可读的过程会直接占满一个core

如果想要减少cpu资源占用的话,又会增加编程的复杂度。

3. I/O多路复用

IO多路复用有select/poll/epoll这样的几种方式

先介绍一下最有代表性的select方法

int select(int nfds, fd_set *restrict readfds,
  fd_set *restrict writefds, fd_set *restrict errorfds,
  struct timeval *restrict timeout);

select方法的返回值代表当前可以操作的fd数量,如果返回值大于0,说明已经有fd准备就绪,下一步我们就可以调用recvfrom方法从就绪的fd中读取数据了(先只考虑可读的情况)

select方法是否阻塞,与timeout参数有关

如果timeout被设置为0,那么select是非阻塞的,对select方法的调用会立即返回。

如果timeout被设置为非0,则select会阻塞,直到有fd可读,或者timeout到期为止。

总的来说,I/O多路复用是同步阻塞的, 但主要是阻塞在对select/poll/epoll方法的调用上,后续的recvfrom则是同步的。

多说一句,I/O多路复用,实际上跟第一条介绍的阻塞IO差不多
只是I/O多路复用可以同时监听多个fd罢了

这样就减少了为每个需要监听的fd开启一个线程的开销。

4. 信号驱动式I/O

没用过也没见过,直接上截图:

5. 异步I/O

同步IO中,在调用recvfrom方法时,即使kernel已经将数据准备好,recvfrom方法也不会立即返回

必须要在耗费一定的时间,将数据从kernel完全拷贝到用户buf中后,recvfrom方法才会返回

也就是说,在recvfrom方法无异常返回的时候,数据已经在buf中准备好了

异步IO则有相当大的不同:

  1. 用户调用一次请求数据的方法,该方法会无阻塞的立即返回。
  2. OS接到这个请求后,会将用户所请求的数据从kernel拷贝到指定的位置。
  3. 数据拷贝完成后,第一步中注册的回调方法会被调用(或者触发一个信号,总之就是要让用户感知到数据已经拷贝完成)
  4. 用户感知到这一事件,此时数据已经准备好,可以直接处理数据了

如下图所示

但是目前Linux的aio还不成熟,而且epoll提供的IO多路复用模型在性能上已经够用了,所以在此就不举例了

ps. NodeJS在Linux上的异步实现是基于libeio,这是用阻塞IO和线程池模拟出来的异步IO

最后上一张图作为总结

原文

https://www.cnblogs.com/stevenczp/p/7479001.html

相关文章

  • java IO、NIO、AIO

    IO流(同步、阻塞) 、 NIO(同步、非阻塞) 、 NIO2(异步、非阻塞) 概述在我们学习Java的IO流之前...

  • IO模型

    原文参考链接 四种状态 同步 异步 阻塞 非阻塞 IO分类 同步阻塞IO 同步非阻塞IO 异步非阻塞IO注意: 没...

  • 阻塞非阻塞 同步异步 IO模型及其应用 NIO实现原理

    1.同步异步概念 2.阻塞非阻塞概念 3.常见I/O模型:同步阻塞IO,同步非阻塞IO,异步阻塞IO,异步非阻塞I...

  • BIO NIO AIO

    BIO:同步阻塞IONIO:同步非阻塞IOAIO:异步非阻塞IO先弄清楚同步、异步,阻塞、非阻塞概念。 io操作分...

  • Java Socket IO演进(一)-BIO/NIO/AIO

    1. 概览 Java中主要有三种IO模型,分别是同步阻塞IO(BIO)、同步非阻塞IO(NIO)、异步非阻塞IO(...

  • UNIX 的5种IO模型介绍

    IO模型同步、异步、阻塞、非阻塞socket阻塞与非阻塞,同步与异步 同步和异步 同步/异步主要针对C端-同步就像...

  • I/O模型

    一般来说I/O模型可以分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO 同步阻塞IO:在此种方式下,用户进程在...

  • Java AIO基础

    Java AIO(异步IO)特性是在Java7引入的。 [TOC] 同步异步、阻塞非阻塞的理解 同步和异步 同步和...

  • Java IO

    Before IO 分为:同步、异步阻塞、非阻塞 同步和异步是目的,阻塞和非阻塞是实现方式。 一个IO操作其实分成...

  • Java中的IO模型

    Java中的IO模型 Java中的IO模型有四种: 同步阻塞IO 同步非阻塞IO IO多路复用 异步IO 其中IO...

网友评论

      本文标题:Java IO 学习(一)同步/异步/阻塞/非阻塞

      本文链接:https://www.haomeiwen.com/subject/ygycqhtx.html