文章目录
- [🍺 来源](#🍺 来源)
- [🍺 C++](#🍺 C++)
-
- [🍻 new 和 malloc 的区别?+2](#🍻 new 和 malloc 的区别?+2)
- [🍻 delete 和 delete[] 的区别?+0](#🍻 delete 和 delete[] 的区别?+0)
- [🍻 内存泄漏是什么?如何避免?+1](#🍻 内存泄漏是什么?如何避免?+1)
- [🍺 计算机网络](#🍺 计算机网络)
-
- [🍻 URL 输入后发生了什么?+1](#🍻 URL 输入后发生了什么?+1)
- [🍻 TLS 握手的过程?+1](#🍻 TLS 握手的过程?+1)
- [🍻 三次握手为什么不能为两次?+1](#🍻 三次握手为什么不能为两次?+1)
- [🍻 四次挥手为什么不能为三次?+1](#🍻 四次挥手为什么不能为三次?+1)
- [🍻 TCP 和 UCP 的区别?应用场景?+1](#🍻 TCP 和 UCP 的区别?应用场景?+1)
- [🍻 HTTP 1.0、1.1 和 2.0 的区别?](#🍻 HTTP 1.0、1.1 和 2.0 的区别?)
- [🍺 操作系统](#🍺 操作系统)
-
- [🍻 进程、线程和协程的区别?+1](#🍻 进程、线程和协程的区别?+1)
- [🍻 线程间的通信方式有哪些?+2](#🍻 线程间的通信方式有哪些?+2)
- [🍻 如何查看磁盘空间?+1](#🍻 如何查看磁盘空间?+1)
- [🍻 如何通过端口号查找进程?+1](#🍻 如何通过端口号查找进程?+1)
- [🍻 缺页中断是什么?+0](#🍻 缺页中断是什么?+0)
- [🍺 MySQL](#🍺 MySQL)
-
- [🍻 InnoDB 和 MylSAM 的区别?+1](#🍻 InnoDB 和 MylSAM 的区别?+1)
- [🍻 索引的注意事项?+1](#🍻 索引的注意事项?+1)
- [🍺 算法](#🍺 算法)
-
- [🍻 实现线程池?+0](#🍻 实现线程池?+0)
🍺 来源
🍺 C++
🍻 new 和 malloc 的区别?+2
🔸 new 是 C++ 的关键字,需要编译器支持;而 malloc 是库函数,需要头文件支持。
🔸 new 申请动态内存时不需要指定大小,编译器会自动计算;而 malloc 申请动态内存时,需要手动计算大小。
🔸 new 分配内存成功时,会返回一个指向对象的指针;而 malloc 会返回一个 void* 类型的指针,需要强制类型转换为其他类型。
🔸 new 分配内存失败时,会抛出异常;而 malloc 则会返回 NULL。
🔸 new 分配内存时,会调用 operator new 申请足够多的内存,然后调用对象的构造函数初始化成员变量;而 malloc 只能申请动态,无法进行对象的构造工作。
🍻 delete 和 delete[] 的区别?+0
🍻 内存泄漏是什么?如何避免?+1
🔸 内存泄漏通常是指堆中内存的泄漏,当使用 new,malloc 分配堆中内存时,使用完毕后未使用 delete,free 进行释放,导致这块内存就无法被再次使用。
🔸 采用记数法,当使用 new 或 malloc 时,让计数器加一,当是用 delete 或 free 时,让计数器减一,程序执行完毕后检查计数器,如果不为 0 则存在内存泄漏。🔸 析构函数需要声明为虚函数,防止父类指针指向子类对象时,编辑器实施静态绑定只会调用父类的析构函数,造成子类对象的析构不完全,导致内存泄漏。
🔸 使用智能指针,自动释放动态内存,避免内存忘记释放而导致的内存泄漏。
🍺 计算机网络
🍻 URL 输入后发生了什么?+1
🔸 首先浏览器会对 URL 进行解析,生成发送给服务器的请求报文。
🔸 查询服务器域名对应的 IP 地址,浏览器会先查询本地缓存,本地缓存没有的话,就从通过 DNS 服务器进行查询。
🔸 查询到服务器的 IP 地址后,向服务器请求连接,进行 TCP 的三次握手,连接后始终保持通信。
🔸 期间浏览器可以向服务器发送 GET,POST 等请求,比如获取、修改数据库中的信息等。
🔸 服务器会对浏览器的请求进行处理,并生成响应报文发送给浏览器。
🔸 浏览器获取响应报文,并进行内容的解析,渲染网页呈现在屏幕上。
🍻 TLS 握手的过程?+1
🔸 TLS 采用混合加密机制,首先采用非对称密钥来加密用于传输的对称密钥,确保对称密钥传输的安全性。之后使用对称密钥来加密传输的数据,确保数据通信的效率。
🔸 首先客户端会生成一个随机数,给出协议版本号和自己支持的加密算法。🔸 服务端确认好双方的加密算法后,会生成一个随机数,给出自己的数字证书。
🔸 客户端确认数字证书有效后,会生成一个新的随机数,并使用数字证书中的公钥加密这个新随机数。
🔸 服务端通过自己的私钥,对客户端发送来的新随机数进行解密。
🔸 最后客户端和服务端使用之前所生成的三个随机数,生成对话密钥,用来加密之后的整个对话过程。
🍻 三次握手为什么不能为两次?+1
🔸 第一次握手主要是为了说明客户端有发送的能力,服务端有接收的能力。第二,三次握手主要是为了说明服务端和客户端具有发送和接收的能力。因此需要三次握手才能确保客户端和服务端的发送接收能力都是正常的。
🔸 两次握手还会出现历史连接的问题。当客户端发送的 SYN 被网络阻塞,同时客户端宕机时,客户端重启后会重新发送一个新的 SYN。由于服务端并不知道先前的 SYN 是历史连接,会进行无效的数据传输,造成资源浪费。
🍻 四次挥手为什么不能为三次?+1
🔸 当服务器收到客户端发送的 FIN 报文时,会先发送一个 ACK 表示自己已经收到信息。
🔸 但此时服务端可能还有数据没有处理完,所以并不会马上关闭连接。只有当服务端的数据全部处理完毕后,才发送 FIN 报文,因此这两个报文通常不会合并发送。
🍻 TCP 和 UCP 的区别?应用场景?+1
🔸 TCP 是面向连接的协议,传输前需要先建立连接;而 UDP 可以不建立连接直接传输。
🔸 TCP 具有可靠性,数据可以无差错,有序,完整的传输;而 UDP 是尽最大可能的交付,不具备可靠性。
🔸 TCP 是一对一的点到点服务;而 UDP 支持一对一,一对多,多对一的服务。
🔸 TCP 有流量控制,拥塞控制,可以调节发送方的发送速率;而 UDP 没有。
🔸 TCP 首部长,开销较大,至少 20 字节;而 UDP 首部较小,只有固定 8 字节。
🔸 TCP 是基于字节流的传输,无边界但是有序;而 UDP 是基于包的传输,有边界但是无序。
🔸 TCP 是面向连接且可靠的,因此主要用于文件传输这种对数据完整性要求高的场景;而 UDP 是无连接不可靠但数据传输比较快的,可以用于音视频通话这种对实时性要求比较高的场景。
🍻 HTTP 1.0、1.1 和 2.0 的区别?
🔸 HTTP 1.0 是一种无状态协议,浏览器每次请求都需要与服务器建立一个 TCP 连接,处理完请求之后立即断开连接,不记录过去的状态。
🔸 HTTP 1.1 支持长连接,在一个 TCP 连接期间可以同时处理多个 HTTP 请求和响应,减少了网络延迟。
🔸 HTTP 2 增加了二进制分帧,多路复用和请求优先级等功能,网络的传输效率得到很大的提高。
🍺 操作系统
🍻 进程、线程和协程的区别?+1
🔸 进程是资源分配的基本单位;线程是 CPU 调度的基本单位;协程是轻量级线程,是线程内部调度的基本单位。
🔸 进程拥有 CPU 资源,内存资源,文件资源等;而线程和协程只拥有自己的寄存器,栈等资源。
🔸 进程和线程的切换内容都保存在用户态,切换时会涉及到用户态到内核态的切换,但是因为线程需要的切换内容比较少,所以效率会更高些;协程的切换内容保存在用户态中,不涉及用户态到内核态的切换,因此切换效率更高。
🔸 进程和线程的切换者是操作系统,切换时机由系统决定;而协程的切换者是用户,切换时机由用户来决定。
🍻 线程间的通信方式有哪些?+2
🔸 线程之间资源共享,所以线程间通信的主要目的是为了线程同步。
🔸 互斥锁 :它是为了在任意时间内,仅有一个线程可以访问共享资源。比如当线程 A 加锁成功时,那么线程 B 再加锁就会失败并进入阻塞睡眠状态,并会释放 CPU 让给其他线程。等待锁被释放后,内核会唤醒线程 B 去加锁继续执行业务。🔸 自旋锁 :它也是为了在任意时间内,仅有一个线程可以访问共享资源。但是当线程获取自旋锁失败时,不会立即释放CPU,而是一直循环尝试获取锁,直到获取锁成功。因此自旋锁一般用于加锁时间很短的场景,减少了线程上下文切换的开销。
🔸 读写锁 :它由读锁和写锁两部分构成,如果只读取共享资源用读锁加锁,如果需要修改共享资源则需要用写锁加锁,可以同时有多个线程进行读,但是最多只能有一个线程进行写。它主要用于可以明确区分读操作和写操作的场景,在读多写少的场景下可以发挥出优势。
🔸 条件变量 :条件变量是一种同步机制,可能使线程进入阻塞状态,并在满足某个条件时解除阻塞继续执行业务。
🔸 信号量 :它是一个整形的计数器,主要用于实现进程间的互斥和同步。信号量的值代表可用资源的数量,控制信号量的方式有 P 操作和 V 操作,分别发生在进入共享资源,离开共享资源时。
🔸 信号:它是线程间的一种异步通信机制,可以在任何时候发送信号给某一线程。信号的来源有硬件来源(ctrl+c 终止进程)和软件来源(kill 命令)等。
🍻 如何查看磁盘空间?+1
🔸 可以用 df 和 du 命令查看磁盘空间。
🔸 df 以磁盘分区为单位查看文件系统,可以获取硬盘被占用了多少空间,还剩下多少空间。🔸 du 用于查看当前目录下磁盘空间的使用情况。
🍻 如何通过端口号查找进程?+1
🔸 可以通过 ps 和 netstat 查找到进程。
🔸ps -ef | grep $pid
🔸
netstat -ntp | grep $pid
🍻 缺页中断是什么?+0
🍺 MySQL
🍻 InnoDB 和 MylSAM 的区别?+1
🔸 InnoDB 支持事务,具有 ACID 属性;而 MyISAM 不支持事务,适用于读多写少的场景。
🔸 InnoDB 支持行级锁,仅锁定实际需要的数据;而 MyISAM 只支持表级锁,需要对整张表锁定。
🔸 InnoDB 支持外键,建立表与表之间的联系,保障了数据的完整性;而 MyISAM 不支持外键。
🔸 InnoDB 在崩溃后可以自动恢复;MyISAM 崩溃后需要手动恢复,比较麻烦。
🔸 InnoDB 支持热备份,即在数据库运行的时候进行备份;MyISAM 只支持冷备份。
🍻 索引的注意事项?+1
🔸 不要在列上使用函数,运算符,否定操作符,这将会导致索引失效而进行全局扫描。
🔸 进行单列的索引合不能有效提高数据的查询效率,应该使用多列的组合索引。
🔸 使用组合索引应该遵循最左前缀原则,即查询中使用了组合索引的第一个字段,索引才会被使用。
🔸 如果索引中存在所查询字段的值,此时会使用覆盖索引,根据索引的查询结果直接返回数据,而不需要回表二次查询。
🔸 对于某一列如果有 NULL 值存在,则不会去使用索引。对于组合索引,只要某列出现 NULL 值,该列对于组合索引就是无效的。
🔸 当查询条件左右两端的数据类型不匹配时,会进行隐式类型转换,可能会导致索引失效而全表扫描。
🔸 当使用 like 进行模糊查询时,查询只有右边有 % 的数据时支持索引,如果左右两边都有 % 会导致索引失效进行全表扫描。