IO模型

1) 同步阻塞IO(Blocking IO)
2) 同步非阻塞IO(Non-blocking IO)
3) IO多路复用(IO Multiplexing)
4) 异步IO(Asynchronous IO)

https://www.cnblogs.com/myJavaEE/p/6721127.html)

1.同步/异步

同步和异步是相对的
同步 前后两件任务, 有严格的顺序一致性(依赖和递进), 按顺序执行, 执行完一个再执行下一个, 需要等待、协调运行
异步 对顺序的要求和依赖关系没那么强, 表现出来就是两个任务可以分给两个人做, 在等待任务A结束时(同步点前)可以进行任务B
多线程就是实现异步的一个方式, 它把"第二件任务"交给其他的线程去做了. 硬件的DMA也是异步.

在实际编程中, 同步和异步区分了请求与响应的交互中, 获取响应的方式
同步: 请求某种结果, 响应返回所需结果
异步: 请求'给我结果', 第一次响应回答'我知道了', 第二次响应通知请求线程'已完成' (通过状态通知或调用请求者注册的回调函数等方式)

2.阻塞/非阻塞

阻塞和非阻塞也是相对概念
阻塞   : 请求-响应比较耗时, 如IO操作
非阻塞: 请求-响应比较迅速, 如没有等待IO完成就直接返回状态值
socket的非阻塞IO需要设置为NONBLOCK

 

下列内容节选自 http://www.cnblogs.com/fanzhidongyzby/p/4098546.html, 感谢原作者!

 

1.同步阻塞IO

最简单的IO模型,用户线程在读写时被阻塞

数据拷贝指请求到的数据先存放在内核空间, 然后从内核空间拷贝至程序的缓冲区

{
    // read阻塞
    read(socket, buffer);
    // 处理buffer          
    process(buffer);
}

用户线程在IO过程中被阻塞,不能做任何事情,对CPU的资源利用率不高

2. 同步非阻塞

用户线程不断发起IO请求. 数据未到达时系统返回一状态值; 数据到达后才真正读取数据

伪代码如下

{
    // read非阻塞   
    while(read(socket, buffer) != SUCCESS);
    process(buffer);
}

用户线程每次请求IO都可以立即返回,但是为了拿到数据,需不断轮询,无谓地消耗了大量的CPU

一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性

3. IO多路复用

IO多路复用建立在内核提供的阻塞函数select上

用户先将需要进行IO操作的socket添加到select中,然后等待阻塞函数select返回。当数据到达后,socket被激活,select返回,用户线程就能接着发起read请求

伪代码如下:

{
    // 注册
    select(socket);
    // 轮询
    while(true) {
        // 阻塞
        sockets = select();
        // 数据到达, 解除阻塞
        for(socket in sockets) {
            if(can_read(socket)) {
            // 数据已到达, 那么socket阻不阻塞无所谓
       read(socket, buffer);
            process(buffer);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/pjl1119/p/9680166.html