服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:
(1)同步阻塞IO(Blocking IO):即传统的IO模型。
(2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。
(3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。
(4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞。
同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。
阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。
有一个很形象的比喻:学生(用户线程)去楼道口打水,水龙头的水(IO)暂时没有,他就在那儿一直等,等到有水,再自己打满然后回去这是阻塞IO。非阻塞IO就是他发现没水以后也不等,就回去然后再来看一下,循环往复,一直到有水的那次,再自己打水。同步和异步的区别就是有没有介入宿管(内核线程),如果学生发现水没有好,然后被宿管员告知回去,然后宿管等到有水之后会自己打好水,最后在告知学生来取,这就是异步IO。所以判断一个IO是异步还是同步主要看IO这件事是用户线程还是内核线程来做。
但是再形象终究还是比喻,要真正理解其行为还是要落实到其内部细节。发现一篇写的不错的博客,尤其几张图片让我叹为观止。直接上图了