IO模型
IO操作分两步:
1)发起IO请求等待数据准备.
2)实际IO操作.
1. 阻塞与非阻塞
阻塞和非阻塞关注的是: 线程在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
2.同步与异步
同步和异步关注的是:消息通信机制
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是 由调用者主动等待这个调用的结果。
而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状通知来通知调用者,或通过回调函数处理这个调用。
同步须要主动读写数据,在读写数据的过程中还是会阻塞。
异步仅仅须要I/O操作完毕的通知。并不主动读写数据,由操作系统内核完毕数据的读写。
同步IO和异步IO是针对用户应用程序和内核的交互。
Unix提供了五种IO模式,分别是:
阻塞IO
非阻塞IO
IO复用
信号驱动IO
异步IO
前四种IO模型都是同步IO操作,区别在于第一阶段,而他们的第二阶段是一样的:在数据从内核复制到应用缓冲区期间(用户空间),进程阻塞于recvfrom调用或者select()函数。 相反,异步I/O模型在这两个阶段都要处理。
阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。
同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO、非阻塞IO、IO复用、信号驱动IO都是同步IO,如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO。
NioEventLoop
NioEventLoop中维护了一个线程,线程启动时会调用NioEventLoop的run方法,执行I/O任务(socket中accept、connect、read、write)和非I/O任务(添加到taskQueue中的任务,如register0、bind0等任务)。
两种任务的执行时间比由变量ioRatio控制,默认为50,则表示允许非IO任务执行的时间与IO任务的执行时间相等。
如果触发了epool cpu100%的bug,会发生什么?
selector.select(timeoutMillis)操作会立即返回,不会阻塞timeoutMillis,导致 currentTimeNanos 几乎不变,这种情况下,会反复执行selector.select(timeoutMillis),变量selectCnt 会逐渐变大,当selectCnt 达到阈值,则执行rebuildSelector方法,进行selector重建,解决cpu占用100%的bug。
[selector 如何修复 epoll bug]
1 对 Selector的select操作周期进行统计
2 每完成一次select操作进行一次计数
3 连续发生N(512)次空轮询则认为触发epoll bug,重新rebuild selector
设计模式
来源:CSDN
作者:qq_38328148
链接:https://blog.csdn.net/qq_38328148/article/details/103845602