From 8df0902abb3f4fb905b158f164a178cd7e30e862 Mon Sep 17 00:00:00 2001 From: yinkanglong_lab Date: Tue, 6 Apr 2021 15:40:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B6=E8=A1=8C=E7=BC=96=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- C++/web开发/sougou-workflow.md | 0 C++/标准库/12 动态内存.md | 2 +- C++/标准库/9 线程.md | 2 ++ 操作系统/附录3 五种IO模型.md | 2 +- 操作系统/附录8 同步异步、阻塞非阻塞.md | 33 ++++++++++++++++++++++---- 5 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 C++/web开发/sougou-workflow.md diff --git a/C++/web开发/sougou-workflow.md b/C++/web开发/sougou-workflow.md new file mode 100644 index 00000000..e69de29b diff --git a/C++/标准库/12 动态内存.md b/C++/标准库/12 动态内存.md index 0d3e8fef..497143b0 100644 --- a/C++/标准库/12 动态内存.md +++ b/C++/标准库/12 动态内存.md @@ -182,7 +182,7 @@ delete [] pa; * unique_ptr动态数组版本 ``` -unique_ptr up(new int[[10]]); +unique_ptr up(new int[10]); up.release(); ``` ![](image/2021-03-06-22-29-22.png) diff --git a/C++/标准库/9 线程.md b/C++/标准库/9 线程.md index f3284231..a95dcdfc 100644 --- a/C++/标准库/9 线程.md +++ b/C++/标准库/9 线程.md @@ -288,6 +288,8 @@ int main() ### package_task说明 * 是一个线程池,可以用来多次启动某一个线程。 * 是async方法的扩展版,通过return语句来抛出一个默认的promise,解锁future的执行。 + + |函数|作用| |---|---| get_future|返回与承诺的结果关联的 std::future diff --git a/操作系统/附录3 五种IO模型.md b/操作系统/附录3 五种IO模型.md index 11fec774..76c411b4 100644 --- a/操作系统/附录3 五种IO模型.md +++ b/操作系统/附录3 五种IO模型.md @@ -42,7 +42,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * ![](image/2021-03-30-22-02-42.png) ### I/O 复用(事件驱动IO) - +* I/O多路复用。I/O指的是I/O事件(包括I/O读写、I/O异常等事件),多路指多个独立连接(或多个Channel),复用指多个事件复用一个控制流(线程或进程)。串起来理解就是很多个独立I/O事件的处理依赖于一个控制流。 * 主要是select、poll、epoll;对一个IO端口,两次调用,两次返回,比阻塞IO并没有什么优越性;关键是能实现同时对**多个IO端口进行监听**; * I/O复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。 * 它可以让**单个进程具有处理多个 I/O 事件的能力**。又被称为 Event Driven I/O,即**事件驱动 I/O**。 diff --git a/操作系统/附录8 同步异步、阻塞非阻塞.md b/操作系统/附录8 同步异步、阻塞非阻塞.md index aa4f2743..e85a3139 100644 --- a/操作系统/附录8 同步异步、阻塞非阻塞.md +++ b/操作系统/附录8 同步异步、阻塞非阻塞.md @@ -14,6 +14,17 @@ * **异步式 I/O (Asynchronous I/O)或非阻塞式I/O (Non-blocking I/O)**。则针对所有I/O 操作不采用阻塞的策略。当线程 遇到I/O 操作时,不会以阻塞的方式等待I/O 操作的完成或数据的返回,而只是将I/O 请求发送给操作系统,继续执行下一条语句。当操作系统完成I /O 操作时,以事件的形式通知执行I/O 操作的线程,线程会在特定时候处理这个事件。为了处理异步I/O,线程必须有事件循环,不断地检查有没有未处 理的事件,依次予以处理。 * **并发方式**。阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过**多线程**。而非阻塞模式下,一个线程永远在执行计算操作,这个线程所使用的CPU 核心利用率永远是100%,**I/O 以事件的方式通知**。在阻塞模式下,多线程往往能提高系统吞吐量,因为一个线程阻塞时还有其他线程在工作,多线程可以让CPU 资源不被阻塞中的线程浪费。而在非阻塞模式下,线程不会被I/O 阻塞,永远在利用CPU。多线程带来的好处仅仅是在多核CPU 的情况下利用更多的核,而Node.js的单线程也能带来同样的好处。这就是为什么Node.js 使用了单线程、非阻塞的**事件编程模式**。 + +### 一种更深的理解——在看完五种IO模型之后的反思 + +* 同步和异步是针对**应用程序和内核**的交互而言的; + * 同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪。 + * 异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。 +* 阻塞和非阻塞是针对于**进程在访问数据**的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式; + * 阻塞方式下读取或者写入函数将一直等待, + * 非阻塞方式下,读取或者写入函数会立即返回一个状态值。 + + ### 同步异步 * 同步与异步关注的是消息通信机制。是**两个进程之间的关系**。 @@ -27,13 +38,23 @@ * 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。 * 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。 -## 3 实现方式 +## 3 实现方式 ### 同步阻塞通信 -* java socket网络编程,都是阻塞通信。接收端在接受到数据之前,一直处于阻塞状态。通过多线程实现并行编程。 +> 在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。 + +* java 传统的IO和socket网络编程,都是阻塞通信。接收端在接受到数据之前,一直处于阻塞状态。通过多线程实现并行编程。 * 在linux下,select/poll/epoll也是同步阻塞IO,也被称为事件IO,同时堵塞多个IO。不需要多线程,当某个IO可用时,发送IO事件,使用事件驱动的IO实现并行编程。 * 普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事。也是通过开启多个浏览器线程实现并行编程。 + +### 同步非阻塞 +> 在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。 + +* poll机制。轮训IO信号,虽然没有阻塞,但是在循环中一致确认IO是否完成。效率很低。 + + ### 异步非阻塞通信 +> 在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。目前Java中还没有支持此种IO模型 * node.js是单线程的异步非阻塞(事件循环检测通知的机制); * windows完全端口是机器上有几个cpu创建几个线程的异步非阻塞机制(多线程池 + 事件触发机制) @@ -41,13 +62,15 @@ * ajax请求(异步): 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕 -### 同步非阻塞 +### 异步阻塞通信 -* poll机制。轮训IO信号,虽然没有阻塞,但是在循环中一致确认IO是否完成。效率很低。 +> 此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄,从而提高系统的并发性! ### 实现并行编程的几种方法 1. java 多线程 2. nodejs 异步回调 -3. linux IO复用。epoll事件回调 \ No newline at end of file +3. linux IO复用。epoll事件回调 + +> 这里所谓的什么机制、什么方法。都是设计模式的一部分。通过某种设计模式,实现并行编程:异步回调模式、事件回调模式等。 \ No newline at end of file