范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

阻塞非阻塞多路复用同步异步BIONIOAIO一文搞定

  关于IO会涉及到阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO等几个知识点。知识点虽然不难但平常经常容易搞混,特此Mark下,与君共勉。 1 阻塞跟非阻塞1.1 阻塞
  阻塞IO情况下,当用户调用 read  后,用户线程会被阻塞,等内核数据准备好并且数据从内核缓冲区拷贝到用户态缓存区后 read  才会返回。可以看到是阻塞的两个部分。 CPU把数据从磁盘读到内核缓冲区。 CPU把数据从内核缓冲区拷贝到用户缓冲区。 1.2 非阻塞
  非阻塞IO发出read请求后发现数据没准备好,会继续往下执行,此时应用程序会不断轮询polling内核询问数据是否准备好,当数据没有准备好时,内核立即返回EWOULDBLOCK错误。直到数据被拷贝到应用程序缓冲区,read请求才获取到结果。并且你要注意!这里最后一次 read 调用获取数据的过程,是一个同步的过程,是需要等待的过程。这里的同步指的是 内核态的数据拷贝到用户程序的缓存区这个过程 。 1.3 IO多路复用
  非阻塞情况下无可用数据时,应用程序每次轮询内核看数据是否准备好了也耗费CPU,能否不让它轮询,当内核缓冲区数据准备好了,以事件通知当机制告知应用进程数据准备好了呢?应用进程在没有收到数据准备好的事件通知信号时可以忙写其他的工作。此时 IO多路复用 就派上用场了。
  IO多路复用中文比较让人头大,IO多路复用的原文叫 I/O multiplexing,这里的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态来同时管理多个I/O流. 发明它的目的是尽量多的提高服务器的吞吐能力。实现一个线程监控多个IO请求,哪个IO有请求就把数据从内核拷贝到进程缓冲区,拷贝期间是阻塞的!现在已经可以通过采用mmap地址映射的方法,达到内存共享效果,避免真复制,提高效率。
  像 select、poll、epoll  都是I/O多路复用的具体的实现。 1.3.1 select
  select是第一版IO复用,提出后暴漏了很多问题。 select 会修改传入的参数数组,这个对于一个需要调用很多次的函数,是非常不友好的。 select 如果任何一个sock(I/O stream)出现了数据,select 仅仅会返回,但不会告诉是那个sock上有数据,只能自己遍历查找。 select 只能监视1024个链接。 select 不是线程安全的,如果你把一个sock加入到select, 然后突然另外一个线程发现这个sock不用,要收回,这个select 不支持的。 1.3.2poll
  poll 修复了 select 的很多问题。 poll 去掉了1024个链接的限制。 poll 从设计上来说不再修改传入数组。
  但是poll仍然不是线程安全的, 这就意味着不管服务器有多强悍,你也只能在一个线程里面处理一组 I/O 流。你当然可以拿多进程来配合了,不过然后你就有了多进程的各种问题。 1.3.3 epoll
  epoll 可以说是 I/O 多路复用最新的一个实现,epoll 修复了poll 和select绝大部分问题, 比如: epoll 现在是线程安全的。 epoll 现在不仅告诉你sock组里面数据,还会告诉你具体哪个sock有数据,你不用自己去找了。 epoll 内核态管理了各种IO文件描述符, 以前用户态发送所有文件描述符到内核态,然后内核态负责筛选返回可用数组,现在epoll模式下所有文件描述符在内核态有存,查询时不用传文件描述符进去了。 1.3.4 三者对比
  横轴 Dead connections 是链接数的意思,叫这个名字只是它的测试工具叫deadcon。纵轴是每秒处理请求的数量,可看到epoll每秒处理请求的数量基本不会随着链接变多而下降的。poll 和/dev/poll 就很惨了。但 epoll 有个致命的缺点是只有 linux 支持。
  比如平常Nginx为何可以支持4W的QPS是因为它会使用目标平台上面最高效的I/O多路复用模型。 1.4 异步IO
  然后你会发现上面的提到过的操作都不是真正的异步,因为两个阶段总要等待会儿!而真正的异步 I/O 是内核数据准备好和数据从内核态拷贝到用户态这两个过程都不用等待。
  很庆幸,Linux给我们准备了 aio_read 跟 aio_write 函数实现真实的异步,当用户发起aio_read请求后就会自动返回。内核会自动将数据从内核缓冲区拷贝到用户进程空间,应用进程啥都不用管。 【文章福利】另外小编还整理了一些C++后端开发面试题,教学视频,后端学习路线图免费分享,需要的可以自行添加:学习交流群点击 正在跳转 加入~群文件共享
  小编强力推荐C++后端开发免费学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂
  2 同步跟异步2.1 同步
  同步跟异步的区别在于 数据从内核空间拷贝到用户空间是否由用户线程完成  ,这里又分为同步阻塞跟同步非阻塞两种。 同步阻塞:此时一个线程维护一个连接,该线程完成数据到读写跟处理到全部过程,数据读写时时线程是被阻塞的。 同步非阻塞:非阻塞的意思是用户线程发出读请求后,读请求不会阻塞当前用户线程,不过用户线程还是要不断的去主动判断数据是否准备OK了。此时还是会阻塞等待内核复制数据到用户进程。他与同步BIO区别是使用一个连接全程等待
  我们以同步非阻塞为例,如下可看到,在将数据从内核拷贝到用户空间这一过程,是由用户线程阻塞完成的。
  2.2 异步
  对于异步来说,用户进行读或者写后,将立刻返回,由内核去完成数据读取以及拷贝工作,完成后通知用户,并执行回调函数(用户提供的callback),此时数据已从内核拷贝到用户空间,用户线程只需要对数据进行处理即可,不需要关注读写,用户不需要等待内核对数据的复制操作,用户在得到通知时数据已经被复制到用户空间。我们以如下的真实异步非阻塞为例。
  可发现,用户在调用之后会立即返回,由内核完成数据的拷贝工作,并通知用户线程,进行回调。 2.3 同步跟异步对比
  同步关注的消息通信机制synchronous communication,在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。
  异步关注消息通信机制asynchronous communication,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。 3 Java IO
  在Java中,我们使用socket进行网络通信,IO主要有三种模式,主要看 内核支持 哪些。 BIO  :同步阻塞IO。 NIO  :同步非阻塞IO。 AIO  :异步非阻塞IO。 3.1 BIO
  同步阻塞IO ,每个客户端的Socket连接请求,服务端都会对应有个处理线程与之对应,对于没有分配到处理线程的连接就会被阻塞或者拒绝。相当于是 一个连接一个线程  。
  BIO特点 : 使用一个独立的线程维护一个socket连接,随着连接数量的增多,对虚拟机造成一定压力。 使用流来读取数据,流是阻塞的,当没有可读/可写数据时,线程等待,会造成资源的浪费。 3.1.1 BIO 样例
  常量: public class Constant {     public static final String HOST = "127.0.0.1";     public static final int PORT = 8080; }
  主类: public class ClientMain {     public static void main(String[] args) {         //开启服务         System.out.println("开启服务,监听端口:" + Constant.PORT);         new Thread(new ServerThread()).start();         //建立一个socket客户端,发起请求         System.out.println("客户端,请求连接,并发送数据");         try {             Socket socket = new Socket(Constant.HOST,Constant.PORT);             //开启新的线程处理socket连接             new Thread(new ClientProcessThread(socket)).start();         } catch (IOException e) {             e.printStackTrace();         }      } }
  服务端监听线程: // 开启服务监听线程,当收到连接请求后,开启新的线程进行处理 public class ServerThread implements Runnable{     @Override     public void run() {         try {             ServerSocket serverSocket = new ServerSocket(Constant.PORT);             while (true){                 Socket socket = serverSocket.accept();                 new Thread(new ServerProcessThread(socket)).start();                 //开启新的线程进行连接请求的处理             }         } catch (IOException e) {             e.printStackTrace();         }     } }
  服务端处理线程: import java.io.*; import java.net.Socket; /**  * 服务端收到连接请求后,处理请求的线程,阻塞式IO  */ public class ServerProcessThread implements Runnable {     private Socket socket;     public ServerProcessThread(Socket socket){         this.socket = socket;     }     @Override     public void run() {         //获取客户端的数据,并写回         //等待响应         try {             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));             String line = "";             String requestStr = "";             System.out.println("来自客户端的数据:"); // 读取客户端数据             while((line = bufferedReader.readLine()) != null){                 requestStr += line;                 System.out.println(line);             }             //  从服务端发给客户端数据             Writer writer = new OutputStreamWriter(socket.getOutputStream());             writer.write("data from server " + requestStr + "r ");             writer.flush();             writer.close();             bufferedReader.close();             socket.close();         } catch (IOException e) {             e.printStackTrace();         }     } }
  客户端: /**  * 维护客户端socket连接的线程,阻塞式IO  */ public class ClientProcessThread implements Runnable {     private Socket socket;     public ClientProcessThread(Socket socket){         this.socket = socket;     }     @Override     public void run() {         //写数据,等待响应,输出响应         String requestStr = "data from client r ";         try {             Writer writer = new OutputStreamWriter(socket.getOutputStream());             writer.write(requestStr);             writer.flush();             socket.shutdownOutput();             //等待响应             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));             String line;             System.out.println("来自服务端的响应:");             while((line = bufferedReader.readLine()) != null){                 System.out.println(line);             }             writer.close();             bufferedReader.close();             socket.close();          } catch (IOException e) {             e.printStackTrace();         }     } }
  3.2 NIO
  同步非阻塞IO之NIO :服务器端保存一个Socket连接列表,然后对这个列表进行轮询,如果发现某个Socket端口上有数据可读时说明读就绪,则调用该socket连接的相应读操作。如果发现某个 Socket端口上有数据可写时说明写就绪,则调用该socket连接的相应写操作。如果某个端口的Socket连接已经中断,则调用相应的析构方法关闭该端口。这样能充分利用服务器资源,效率得到了很大提高,在进行IO操作请求时候再用个线程去处理,是 一个请求一个线程  。Java中使用Selector、Channel、Buffer来实现上述效果。
  每个线程中包含一个 Selector  对象,它相当于一个通道管理器,可以实现在一个线程中处理多个通道的目的,减少线程的创建数量。远程连接对应一个channel,数据的读写通过buffer均在同一个 channel  中完成,并且数据的读写是非阻塞的。通道创建后需要注册在 selector  中,同时需要为该通道注册感兴趣事件(客户端连接服务端事件、服务端接收客户端连接事件、读事件、写事件), selector  线程需要采用 轮训  的方式调用 selector  的 select  函数,直到所有注册通道中有兴趣的事件发生,则返回,否则一直阻塞。而后循环处理所有就绪的感兴趣事件。以上步骤解决BIO的两个瓶颈: 不必对每个连接分别创建线程。 数据读写非阻塞。
  下面对以下三个概念做一个简单介绍,Java NIO由以下三个核心部分组成: selector  :Selector 允许单线程处理多个Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。要使用Selector,得向Selector注册Channel,然后调用他的select方法,这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子入有新连接接进来,数据接收等。 Channel  :基本上所有的IO在NIO中都从一个Channel开始。Channel有点像流,数据可以从channel 读 到buffer,也可以从buffer 写 到channel。 Buffer  :缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松的使用内存块,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变换情况,Channel提供从文件,网络读取数据的渠道,但是读取或者写入的数据都必须经由Buffer。
  channel和buffer有好几种类型。下面是Java NIO中的一些主要channel的实现: FileChannel DatagramChannel SocketChannel ServerSocketChannel
  正如你所看到的,这些通道涵盖了UDP和TCP网络IO,以及文件IO。以下是Java NIO里关键的buffer实现: ByteBuffer CharBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer
  在微服务阶段,一个请求可能涉及到多个不同服务之间的跨服务器调用,如果你想实现高性能的PRC框架来进行数据传输,那就可以基于Java NIO做个支持长连接、自定义协议、高并发的框架,比如Netty。Netty本身就是一个基于NIO的网络框架, 封装了Java NIO那些复杂的底层细节,给你提供简单好用的抽象概念来编程。比如Dubbo底层就是用的Netty。
  3.3 AIO
  AIO是异步非阻塞IO,相比NIO更进一步,进程读取数据时只负责发送跟接收指令,数据的准备工作完全由操作系统来处理。 参考资料
  推荐一个零声教育C/C++后台开发的免费公开课程,个人觉得老师讲得不错,分享给大家:C/C++后台开发高级架构师,内容包括Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂 立即学习
  原文:阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一锅端

自制奶茶水果捞热天最适合吃各种奶茶喝水果捞了,自己在家做虽然麻烦一点,但乐在其中。因为小孩也特别喜欢吃,所以我在网上买了芋圆粉,西米,脆波波,奶茶桶(在家吃也需要仪式感嘛)。前几天做好芋圆了,今凉拌汁要怎么调才好吃呢?凉拌汁这样调,拌啥都好吃一到夏季,天气一天比一天热,食欲也一天不如一天,简单可口的凉拌菜成了人们的最爱。凉拌菜好不好吃主要取决于凉拌汁。那么,凉拌汁是什么?凉拌汁就是把姜葱蒜辣椒等用酱油醋和香油食盐等调味一锅烧烤味的小花卷这样做,香甜软糯,好吃又好看今天呀我用最简单的方法蒸了一锅烧烤味的小花卷。这样做的小花卷呀,不吃菜都能吃上一盘,一起来看一下吧。三百克的面粉中加入三克酵母粉,一勺白糖,倒入一百六十毫升的温水和成光滑的面团,直超市熟食区里18。9元一整只的烤鸡,能吃吗?漫画为你揭露真相逛超市时相信大家都有这么一个疑惑,超市熟食区里一整只烤鸡售价居然只要20多元,超市搞活动时,可能只需要18。9元一只,有时遇上外卖搞活动,凑满减,或许也只需要20多元,这种烤鸡炸鸡夏天闷热没胃口,若不差钱,试试这5道家常菜,米饭得多备一碗还有几天就到7月了,马上就要开始进入三伏天。三伏天的天气大家是知道的,暴晒无比,都能把人给烤熟了。这段时间特别容易中暑生病,没有胃口,因此在饮食上也需要调节一下,多吃瓜果蔬菜。下面为什么你做的风味茄子不够酥脆,而且还吸了很多油?教你正确做法今天分享一道麻辣鲜香,酸甜酥脆,饭店卖得非常火爆,几乎桌桌必点,放凉了都不会回软的特色风味茄子。这道菜原材料非常简单,虽然不放肉,但是胜似吃肉。食材茄子青红椒香菜生姜生葱大蒜青花椒顶级阵容现身巴黎!LISA朴宝剑防弹V同框粉丝嗨翻近日韩国女团BLACKPINK的LISA,跟韩国演员朴宝剑防弹少年团的成员V,前往法国参加时装周,现身时让在场暴动,3人都拥有超级多粉丝,神仙阵容引起关注。一出现引起粉丝暴动,韩团我终于开启了在恒美的植发之路相比于其他的女生的发际线来说,我的发际线真的是后移比较严重,也显得我的脑门格外的大。在上大学之前,周围的人总是说,大脑门的人聪明,随着年龄的不断增大,我更是凭借着自己的努力,考上了身体缺硒的症状有哪些?身体缺硒怎么办?微量元素硒是一种重要的矿物质,对人体健康非常重要。硒过量和硒缺乏都会导致症状,甚至增加某些疾病的风险,例如癌症或心血管疾病。在国外一些国家,由于贫硒土壤,某些人群的硒供应可能不足。高血脂能喝咖啡吗?提醒稳定血脂,5种食物别错过三高疾病主要包括高血压高血糖和高血脂,但是大多数人对于高血压和高血糖了解的更深入一些,因为人们对于高血脂并不是特别的了解,因此就算是被告知存在血脂偏高的现象,也可能不会那么的着急。怎么吃更健康?跟着新版膳食指南学起来民以食为天,养成良好的健康饮食习惯,保证科学合理的饮食搭配,是身体健康的重要保障。2022年4月,中国居民膳食指南(2022)正式发布,中国人的吃饭指南更新啦!新版膳食指南提炼出了
实验验证非晶合金超稳定性来源中国科学院非晶合金能否长时间保持稳定?非晶材料稳定性的物理机制和根源是什么?这些都是非晶合金材料和物理领域的重要难题。众所周知,非晶态物质的无序原子排列结构特征,导致其相比晶体华为mate50值不值得购买有一颗中国芯叫麒麟,有一个属于Chinese的系统叫鸿蒙,有一个民族企业叫华为!HUAWEI全场景秋季新品发布会不懂的靠边站,别再喷了我承认华为在整机素质上不如苹果不过我相信的是世512G或被迫成刚需!谁是内存刺客?你有过储存不足被迫换机吗曾几何时,512G的机型只是少数人的选择,在当时128G完全可以满足各种日常使用,上256G的大部分都是游戏党或下载党,那会大家为内存买单的意愿还不是很大。可是在软件体积膨胀数倍的苹果新品发布会前瞻iPhone全系列售价或上涨15首款AppleWatchPro将推出科创板日报9月7日讯(编辑邱思雨)据苹果官方消息,今年的新品发布会将于北京时间9月8日凌晨1点开始。相关爆料显示,iPhone14系列AppleWatchPro和新款AirPods挣扎求生的华为VS如日中天的苹果,同期发布,如此对决还有悬念?(华为VS苹果)文馆长Zero最近一段时间,在数码领域尤其是手机这一块,苹果和华为可以说是热搜榜的两大主角了,你方唱罢我登场,你用挖孔屏,我用刘海屏你搞4800万像素影像,我就搞X华为Mate50亮相,共有三款型号9月6日下午两点半,在华为Mate50系列及全场景新品秋季发布会上,华为正式发布Mate50系列手机。余承东上场后先是简单介绍了Mate系列10年以来的成就,随后正式向用户们展示了捅破天华为Mate50系列北斗卫星消息服务解读9月6日,华为新品发布会顺利召开,华为Mate50系列如期而至,同时Mate50系列的一些黑科技也展现给了大众,其中北斗卫星通讯服务通过华为的宣传页面介绍受到了网友的广泛关注。前两面对小米12su,苹果14系列丝毫不虚,华为mate50系列参数详情处理器方面华为Mate50全系4G,E是778G,标准Pro和RS都是骁龙8(台积电)内存方面RS是12G运存,标准和Pro都是8G运存屏幕方面标准版和E为京东方1。5k分辨率加9S12总决赛参赛队伍已经基本确定,官方正式公布赛程随着S12总决赛的脚步临近,各大赛区夏季赛也基本结束,能够参加S12的队伍名单已经确定23个,只剩下土耳其赛区未决出最后一个参赛席位,23支队伍名单如下中国LPLJDGTESEDG游戏都这么涩气了,为什么彷徨之街还是陷入了争议?星彡P丨文我第一次知道百合风俗,还是在大妈之家看了永田的漫画因为太寂寞了而叫了百合风俗小姐的报告(现在应该下架了)。与其说是漫画作品,不如说是作者根据自己亲身经历写了体验报告。主角R星官网更新致谢名单,告别GTA5?或准备正式公开GTA6?相信许多小伙伴都有玩过侠盗猎车手系列GTA5吧,但你们可能不知道的是这款游戏已经接近了9岁的高龄了。近日r星似乎要更新官网thankyou的致谢名单,这一举动是否在告别GTA5?打为什么美国不让用华为通信设备了?因为它和瞎了无异华为Mate50首发支持北斗卫星消息(一)国家有多偏爱华为?没想到北斗通信竟然应用在了手机上,而且是华为!足可见国家对华为的偏爱。要知道在此之前,北斗卫星可是一直应用在军事上!咱们还是走到了这一步,蓝光烟台公司破产清算出品乐居烟台IDytleju编辑李晓娜2021年7月,千亿黑马蓝光发展出现债务违约,至今一年时间,仍未走出债务泥潭。四年前,这位四川地产一哥进驻烟台。首发地牟平,时隔三个月落脚高新汇率一夜破7!人民币应如何反制破局美元霸权?拍案栏目介绍远处江湖,嬉笑苦情乐情人间情不居庙堂,纵论家事国事天下事!太疯狂了!就在刚刚!!人民币兑美元汇率再次跌破7!!!那么,我们会被美元周期性收割并在国内引发输入性通货膨胀吗氢气真的有颜色吗六氟化硫氢主要以化合物的形式存在于地球上的水和化石燃料中。作为二次能源,氢气必须通过制氢技术获得。目前,大多数现有的制氢技术依赖化石能源,无法避免二氧化碳排放。根据氢能的产生来源和太阳系八大行星的运行轨道为什么在同一个平面上?如果你对太阳系的模式进行了更深入的研究,就会发现太阳,行星,卫星和小行星几乎是在一个平面上。为什么各大行星的运行轨道会在一个水平面上?类似的现象在其他星系成立吗?太阳系中的已知八大南沙珊瑚岛礁发育演化研究获进展星罗棋布于南海的珊瑚礁是南海最重要且独特的地质体,在生态和气候环境变化研究等方面发挥重要作用。中国科学院南海海洋研究所科研团队,以揭示珊瑚礁的形成过程和发育模式为主要科学目标之一,我们普通人,怎么就没有无限可能了近段时间,NASA连续发布詹姆斯韦布太空望远镜捕捉的星系照片,让我们可以比以往任何时候都更远更深更清楚地看到太空。但,还是那个老生常谈的问题。对于眼前的生活,仰望星空到底有什么意义论网络游戏的利弊何为游戏?其中心语为戏。戏本义为古时祭祀或进餐时,有人头戴虎头面具持戈舞蹈。后来引申为与娱乐相关的行为,如京戏马戏叶子戏。游义为交游来往,如请息交以绝游。故游戏一词可解释为互动性的广东队没给苏伟注册,苏伟将抱着顶薪退役,苏老英雄才是大赢家广东队没给苏伟注册,苏伟将抱着顶薪退役,苏老英雄才是大赢家广东男篮休赛期变化很大,周鹏加盟了深圳男篮,威姆斯加入山西男篮,汤杰被广东男篮放弃,面临无球可打,王薪凯也到各支球队去试训一周三赛,疲惫红军惊魂绝杀北京时间9月1日凌晨300分,英超第5轮继续进行,利物浦主场对阵纽卡斯尔。上一场90血洗伯恩茅斯,利物浦终于抬起了高贵的头颅,本场主场面对土豪球队纽卡斯尔,是一个难啃的硬骨头。球队英冠战报伯明翰10罗瑟汉姆北京时间9月1日凌晨,20222023赛季英格兰足球冠军联赛结束第七轮较量。本轮比赛中,卡迪夫城12输给卢顿,女王公园巡游者31战胜赫尔城。米尔沃尔客场两球负于伯恩利迎来三连败,诺