文章译自 Aliaksandr Liakh 所写的 《Java sockets I/O: blocking, non-blocking and asynchronous》[1]。
译者注:
作为一个没学过操作系统知识而直接学编程的人,对于阻塞、非阻塞、异步的认知,总感觉隔着一层纱。自上次翻译过 《Event Loop 解疑》 后,它让我对异步的理解深入了一些,趁热打铁,再译一篇相关的主题。
文章比较长,将分为多篇展开。
上一篇,我们讲解了阻塞、非阻塞和异步的基本概念,这一篇继续介绍对应这些概念的几类常见的 I/O 模型。
I/O models
下面是兼容 POSIX 的操作系统中最常见的 I/O 模型:
-
blocking I/O model: 阻塞 I/O 模型 -
non-blocking I/O model: 非阻塞 I/O 模型 -
I/O multiplexing model: I/O 多路复用模型 -
signal-driven I/O model: 信号驱动 I/O 模型 -
asynchronous I/O model: 异步 I/O 模型
Blocking I/O model
在 阻塞 I/O 模型 中,应用程序发出一个会阻塞的系统调用(system call),直到内核(kernel)接收到数据,并把数据从内核空间复制到用户空间。
优点:
-
实现起来最简单的 I/O 模型。
缺点:
-
应用会阻塞。
Non-blocking I/O model
在 非阻塞 I/O 模型 中,应用程序进行的系统调用会立即返回下面两个响应中的一个:
-
如果 I/O 操作可以立即完成,则返回数据。 -
如果 I/O 操作不能立即完成,则返回一个错误码,表示 I/O 操作会阻塞或设备暂时不可用。
为了完成 I/O 操作,应用程序应该忙于等待(busy wait,通过重复的系统调用不断轮询),直到数据可用。

优点:
-
应用不会被阻塞。
缺点:
-
由于应用程序要不断检查数据可用性,这将导致许多从用户态到内核态的上下文切换。 -
这种模式可能带来 I/O 延迟,因为从数据在内核中可用到数据被应用读取之间存在间隔。
I/O multiplexing model
在 I/O 多路复用模型 中(也称为带阻塞通知的非阻塞 I/O 模型,non-blocking I/O model with blocking notifications),应用程序发出一个阻塞的 select 系统调用,来监视多个描述符(descriptors)的活动。对于每个描述符,都可以请求获知某些 I/O 操作(连接、读或写、发生错误等)的准备情况。当 select 系统调用返回时,说明至少有一个描述符准备就绪了,应用程序接着执行非阻塞调用,将数据从内核空间复制到用户空间。
优点:
-
允许在一个线程中对多个描述符执行 I/O 操作。
缺点:
-
在进行 select 系统调用时,应用仍然是阻塞的。 -
不是每种操作系统都能高效地支持这种模式。
Signal-driven I/O model
在 信号驱动的I/O模型 中,应用程序进行非阻塞调用并注册一个信号处理程序。当一个描述符准备好进行 I/O 操作时,就会为应用程序生成一个信号,然后信号处理程序将数据从内核空间复制到用户空间。

优点:
-
应用不会被阻塞。 -
信号方式提供了较好的性能。
缺点:
-
并非所有操作系统都支持信号。
Asynchronous I/O model
在 异步 I/O 模型(也称为重叠 I/O 模型,overlapped I/O model)中,应用程序进行非阻塞调用,并在内核中启动一个后台操作(background operation)。当操作完成后(内核接收到数据,并将其复制到用户空间),会产生一个完成回调(completion callback )来结束 I/O 操作。
异步 I/O 模型 和 信号驱动 I/O 模型 的区别在于,在信号驱动 I/O 中,内核告诉应用程序何时可以启动 I/O 操作,但在异步 I/O 模型中,内核告诉应用程序 I/O 操作是何时完成的(两者将数据从内核空间复制到用户空间的时机不同)。

优点:
-
应用不会被阻塞。 -
该模型提供了最好的性能。
缺点:
-
是实现起来最复杂的 I/O 模型。 -
并非每种操作系统都能高效地支持这种模式。
译者提醒:上面的几类 I/O 模型,大家一定要多读几遍,彻底消化。
Java I/O APIS
有了对以上各类 I/O 模型的理解,接下来谈谈 Java 语言中是如何实现并使用它们的。
… 不要走开。
参考资料
Java sockets I/O: blocking, non-blocking and asynchronous: https://liakh-aliaksandr.medium.com/java-sockets-i-o-blocking-non-blocking-and-asynchronous-fb7f066e4ede
– END –
原文始发于微信公众号(背井):Java Sockets I/O: 阻塞、非阻塞与异步(二)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246733.html