【Java IO】同步异步和阻塞非阻塞真正的区别!!!

news2024/9/21 2:36:26

先上结论:

同步异步和阻塞非阻塞真正的区别!!!

假设某个进程正在运行下面这段代码:

......
operatorA......;
read();
operatorB......;
operatorC......;

当进程执行完operatorA后开始进行read系统调用,而所需数据尚未准备好,这时进程有两种选择:

  1. 等待数据准备好,然后再运行operatorB,operatorC
  2. 不等待数据的准备,直接运行operatorB,operatorC

同步和异步

第1种就是同步方式,第2种就是异步方式,同步和异步描述的是进程的IO操作与其之后的各指令之间运行的先后顺序及依赖关系
先不谈同步和异步如何实现,先来看为什么有同步或者异步的需求:
当operatorB,operatorC等后续操作依赖于read读入的数据时,程序必须停留在read这一步直至数据完全准备好,否则程序会出现错误的结果,这就是所谓“同步
而当operatorB,operatorC等后续操作与read读入的数据无关时,完全可以让当前线程继续执行下去,与后台的IO操作同时进行,这就是所谓“异步
这里可以做一下同义词转换:同步——必须保证某种指令顺序;异步——一段代码中指令执行互相没有依赖,不需要保证顺序

阻塞和非阻塞

继续看第1种情况,也就是进程等待数据准备好再执行operatorB,operatorC的同步方式,即使是等待,也有两种不同的“等待”:

  1. 主动放弃CPU,在阻塞态下等待
  2. 占用CPU进行轮询,在运行态下等待

第1种就是阻塞方式,第2种就是非阻塞方式。也就是说:阻塞和非阻塞这一对概念是在同步的基础上才有了意义,在异步下进程是“继续执行”而不是“等待”,于是不可能会涉及“以何种姿态等待”的问题,即阻塞和非阻塞这对概念描述的问题
如果学过操作系统的朋友可以感觉到:阻塞方式就是操作系统中的“中断驱动”方式,而非阻塞方式就是操作系统中的“程序控制”方式,显然前者的优点是可以更高效地使用系统资源,而后者的优点是实时性,即保证read所需的数据准备好的一瞬间就让进程继续往下执行operatorB和operatorC,而不是接受中断后进入就绪态,等待操作系统漫长的(相对而言)和不稳定的进程调度才得以继续执行


下面是对一篇讲解 Java IO 底层原理的优秀博客所做的阅读笔记和精华摘抄,原文链接为:10分钟看懂, Java NIO 底层原理

Java程序IO的本质(或操作系统IO的本质)

  • read系统调用,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区复制到内核缓冲区。这个两个系统调用,都不负责数据在内核缓冲区和磁盘之间的交换。底层的读写交换,是由操作系统kernel内核完成的。

阻塞和非阻塞

  • 阻塞是指用户空间(调用线程)一直在等待,而且别的事情什么都不做;
  • 非阻塞是指用户空间(调用线程)拿到状态就返回,IO操作可以干就干,不可以干,就去干的事情。
    在java中,默认创建的socket都是阻塞的。

同步和异步

  • 同步IO是指用户空间线程是主动发起IO请求的一方,内核空间是被动接受方。
  • 异步IO则反过来,是指内核kernel是主动发起IO请求的一方,用户线程是被动接受方,用户空间线程向内核空间注册各种IO事件的回调函数,由内核去主动调用

三种IO模型

同步阻塞IO(Blocking IO)

BIO的优点:

  • 程序简单,在阻塞等待数据期间,用户线程挂起。用户线程基本不会占用 CPU 资源。

BIO的缺点:

  • 一般情况下,会为每个连接配套一条独立的线程,或者说一条线程维护一个连接成功的IO流的读写。在并发量小的情况下,这个没有什么问题。但是,当在高并发的场景下,需要大量的线程来维护大量的网络连接,内存、线程切换开销会非常巨大。因此,基本上,BIO模型在高并发场景下是不可用的

注意:不要混淆这里的阻塞IO和操作系统课里学的学的IO模型,操作系统里面学的IO模型是为了节省CPU资源而设计的,概念位于现在所说的JavaIO模型的下层,对Java程序而言是不可见的,而BIO、NIO、AIO是在操作系统的IO模型的上层又发展出的概念,是Java程序可见可控的

同步非阻塞NIO(None Blocking IO)

在linux系统下,可以通过设置socket使其变为non-blocking。NIO 模型中应用程序在一旦开始IO系统调用,会出现以下两种情况:

(1)在内核缓冲区没有数据的情况下,系统调用会立即返回,返回一个调用失败的信息。

(2)在内核缓冲区有数据的情况下,是阻塞的,直到数据从内核缓冲复制到用户进程缓冲。复制完成后,系统调用返回成功,应用进程开始处理用户空间的缓存数据。

NIO的优点:

  • 每次发起的 IO 系统调用,在内核的等待数据过程中可以立即返回。用户线程不会阻塞,实时性较好

NIO的缺点:

  • 需要不断的重复发起IO系统调用,这种不断的轮询,将会不断地询问内核,这将占用大量的 CPU 时间,系统资源利用率较低

点评:NIO有点是“牺牲一切为实时性服务”
Java NIO(New IO) 不是IO模型中的NIO模型,而是另外的一种模型,叫做IO多路复用模型( IO multiplexing )

IO多路复用模型

IO多路复用模型是同步的,也是阻塞的,和BIO的区别就是一个线程可以监听成百上千个文件描述符,减轻了操作系统创建那么多个线程的负担

异步IO模型(asynchronous IO)

  • 当用户线程调用了read系统调用,立刻就可以开始去做其它的事,用户线程不阻塞
  • 在内核kernel的等待数据和复制数据的两个阶段,用户线程都不是block(阻塞)的
  • 用户线程需要注册IO操作完成的回调函数到操作系统的内核
  • 异步IO有的时候,也叫做信号驱动 IO
  • 真正的异步 I/O 模型
  • Windows 系统下通过 IOCP 实现了真正的异步 I/O。但是很少作为百万级以上或者说高并发应用的服务器操作系统来使用。而在 Linux 系统下,异步IO模型目前并不完善。所以在 Linux 下实现高并发网络编程时都是以 IO 复用模型模式为主。

参考资料:
IO 模型知多少 | 理论篇
10分钟看懂, Java NIO 底层原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1441470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习系列——(二十)密度聚类

引言 在机器学习的无监督学习领域,聚类算法是一种关键的技术,用于发现数据集中的内在结构和模式。与传统的基于距离的聚类方法(如K-Means)不同,密度聚类关注于数据分布的密度,旨在识别被低密度区域分隔的高…

TCP/IP协议以及UDP(超详细,看这一篇就够了)

💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录专栏:TCP/IP协议以及UDP(超详细,看这一篇就够了) 🎉欢迎大家点赞👍评论📝收藏⭐文章 TCP/IP协议以及UDP(超详细,看这一篇就够了 前提概括接收端和发送端客户…

[Java][算法 双指针]Day 02---LeetCode 热题 100---04~07

LeetCode 热题 100---04~07 第一题:移动零 思路 找到每一个为0的元素 然后移到数组的最后 但是需要注意的是 要在给定的数组原地进行修改 并且其他非零元素的相对顺序不能改变 我们采用双指针法 定义两个指针i和j i和j一开始分别都在0索引位置 然后判断j所…

Node.js之npm单独与批量升级依赖包的方式

Node.js之npm单独与批量升级依赖包的方式 文章目录 Node.js之npm单独与批量升级依赖包的方式npm查看与升级依赖包1. 单独安装或升级最新版本2. 查看依赖但不升级1. npm outdated2. npm update 3. 批量升级新版本4. npm-check-updates1. 全局安装2. ncu查看可升级的版本3. 升级依…

排序算法---堆排序

原创不易,转载请注明出处。欢迎点赞收藏~ 堆排序(Heap Sort)是一种基于二叉堆数据结构的排序算法。它将待排序的元素构建成一个最大堆(或最小堆),然后逐步将堆顶元素与堆的最后一个元素交换位置&#xff0c…

新年新展望

去年其实是收获颇丰的一年,除了工作中各项工作都得到了很大的推进,个人生活中也有很多变化,其中还拿到了功能安全工程师的证书,以及功能安全经理的证书。 展望一下2024年准备输出的内容,一个是对ISO26262的解读&#x…

手把手教你开发Python桌面应用-PyQt6图书管理系统-图书添加模块-图书类别ComboBox下拉框初始化数据实现

锋哥原创的PyQt6图书管理系统视频教程: PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

Java玩转《啊哈算法》纸牌游戏之小猫钓鱼

缘起性空 文章目录 缘起代码地址纸牌游戏分析代码演示优化 缘起 各位小伙伴们好呀,还有几天就要过年了,祝大家新年快乐,万事胜意! 本人最近看了下《啊哈算法》,确实阔以。 但稍显遗憾的是,书籍示例代码是…

Web后端开发:登录认证案例

登录功能 需求分析 在登录界面中,输入用户的用户名以及密码,然后点击 “登录” ,服务端判断用户输入的用户名和密码是否都正确。如果正确,则返回成功结果,前端跳转至系统首页面;否则报错,停留在…

火星符号运算 - 华为OD统一考试

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 已知火星人使用的运算符号为 #和$ 其与地球人的等价公式如下 x#y2*x3*y4 x$y3*xy2x y是无符号整数。地球人公式按照c语言规则进行计算。火星人公式中&#xff0…

Qt PCL学习(三):点云滤波

注意事项 版本一览:Qt 5.15.2 PCL 1.12.1 VTK 9.1.0前置内容:Qt PCL学习(一):环境搭建、Qt PCL学习(二):点云读取与保存 0. 效果演示 1. pcl_open_save.pro QT core guigr…

【RT-DETR改进涨点】更加聚焦的边界框损失Focaler-IoU、InnerFocalerIoU(二次创新)

一、本文介绍 本文给大家带来的改进机制是更加聚焦的边界框损失Focaler-IoU已经我进行二次创新的InnerFocalerIoU同时本文的内容支持现阶段的百分之九十以上的IoU,比如Focaler-IoU、Focaler-ShapeIoU、Inner-Focaler-ShapeIoU包含非常全的损失函数,边界框的损失函数只看这一…

MySQL-视图/储存过程/触发器

一、视图 1.介绍 视图(View)是一种虚拟存在的表。视图中的数据并在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。 通俗的讲,视图只保存了查询的SQL逻辑,不保…

幻兽帕鲁服务器搭建,阿里云和腾讯云随便选,看看哪个简单?

幻兽帕鲁官方服务器不稳定?自己搭建幻兽帕鲁服务器,低延迟、稳定不卡,目前阿里云和腾讯云均推出幻兽帕鲁专用服务器,腾讯云直接提供幻兽帕鲁镜像系统,阿里云通过计算巢服务,均可以一键部署,鼠标…

Redis核心技术与实战【学习笔记】 - 23.Redis 主从切换故障,有哪些坑

前言 Redis 的主从同步机制不仅可以让从库服务更多的读请求,分担主库的压力,而且还能在主库发生故障时,进行主从库切换,提供高可靠服务。 不过,在实际使用主从机制时会踩到一些“坑”:主从数据不一致、读…

数据结构第十四天(树的存储/双亲表示法)

目录 前言 概述 接口: 源码: 测试函数: 运行结果: 往期精彩内容 前言 孩子,一定要记得你的父母啊!!! 哈哈,今天开始学习树结构中的双亲表示法,让孩…

YOLOv5独家原创改进:大核卷积涨点系列| Shift-ConvNets,稀疏/移位操作让小卷积核也能达到大卷积核效果 | 2024年最新论文

💡💡💡本文独家改进:大的卷积核设计成为使卷积神经网络(CNNs)再次强大的理想解决方案,Shift-ConvNets稀疏/移位操作让小卷积核也能达到大卷积核效果,创新十足实现涨点,助力YOLOv8 💡💡💡在多个私有数据集和公开数据集VisDrone2019、PASCAL VOC实现涨点 收录…

VSCode如何让先前打开的文件不被自动关闭,一直保持在标签栏里(关闭预览模式)

第一次接触VSCode-Huawei IDE编辑器,每次打开一个新的代码文件,旧的代码文件都会被自动关闭(现在才知道是因为文件默认是以预览模式打开展示的)。 那么如何才能让先前打开的文件一直保持在标签栏里呢? 我们需要去设置…

Mac电脑如何通过终端隐藏应用程序?

在我们使用Mac电脑的时候难免会遇到想要不想看到某个应用程序又不想卸载它们。值得庆幸的是,macOS具有一些强大的文件管理功能,允许用户轻松隐藏(以及稍后显示)文件甚至应用程序。 那么,Mac电脑如何通过终端隐藏应用程…

Composition Local

1.显示传参 package com.jmj.jetpackcomposecompositionlocalimport org.junit.Testimport org.junit.Assert.*/*** 显示传参*/ class ExplicitText {private fun Layout(){var color:String "黑色";//参数需要通过层层传递,比较繁琐Text(color)Grid(c…