暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

富途-后端c++一面(很基础)

阿Q正砖 2023-10-01
303

大家好,我是阿Q。

先祝大家国庆节快乐!

十月,对于每个校招er都是一个新的开始。“金九银十”,这也是你最后的一个黄金月。今年后边的话,大规模的校招可能不太会有了,所以抓住这一个月的时间,好好看看面经,巩固自己的基础知识,捋捋自己的项目。

今天给大家水一篇富途后端C++的面经。我最近还总结了其它大小公司的面经,供大家学习巩固。只要你肯努力,一切皆有可能!

虽然可能你已经出去玩、放松休息了,但是不要紧,我依然会将有用的东西整理分享给大家。

来源:

https://www.nowcoder.com/discuss/535934289968402432

总体时间1h多几分钟
面试官人感觉挺不错的,全程语气都挺温和,不会为难
1、手撕 字符串去除相邻重复的字母
    #include <iostream>
    #include <string>


    std::string removeAdjacentDuplicates(const std::string& input) {
    std::string result;

    for (char currentChar : input) {
    // 如果结果字符串为空或者当前字符与结果字符串的最后一个字符不同,将当前字符添加到结果字符串中
    if (result.empty() || currentChar != result.back()) {
    result += currentChar;
    }
    }


    return result;
    }


    int main() {
    std::string input = "aaabbcdddeefffgghhh";
    std::string result = removeAdjacentDuplicates(input);

    std::cout << "Original String: " << input << std::endl;
    std::cout << "Processed String: " << result << std::endl;

    return 0;
    }
    结果输出:
    2、简单问了点项目
    3、问动态库?
    动态库(Dynamic Link Library,DLL)是一种包含可执行代码和数据的文件,它可以在运行时被加载到内存中并供多个程序共享使用。与静态库不同,动态库在程序运行时动态加载,这意味着多个程序可以共享同一个动态库文件,从而节省磁盘空间和内存,并使库的更新更加方便。
    4、怎么找到动态库?
    要找到动态库,需要告诉编译器和链接器库的位置。
    1. 在Linux系统上,动态库通常位于 /lib
      /usr/lib
      或自定义的库路径下。如果你自己编译了一个动态库,库文件通常会在当前目录下或自定义的库路径下。
    2. 在Windows系统上,动态库通常具有 .dll
      扩展名,它们可以位于系统目录、应用程序目录或自定义路径下。系统目录通常是 C:\Windows\System32
      。应用程序目录是包含可执行文件的目录。
    5、找不到动态库怎么办?
    1. 确保库文件位于你指定的搜索路径中。你可以使用绝对路径或相对路径,但要确保路径是正确的。
    2. 确保你使用了正确的库文件名。在 -l
      选项中,通常不需要包含库文件的前缀(如 lib
      )或扩展名(如 .dll
      .so
      )。
    3. 在Windows系统中,确保动态库文件位于系统的 PATH 环境变量指定的路径中。这样可以使操作系统能够找到库文件。
    4. 确保库文件实际存在于指定的路径中。你可以使用文件浏览器或命令行来验证。
    5. 如果你的库依赖于其他库,确保这些依赖库也可用,并且路径正确。如果依赖关系出现问题,可能导致库加载失败。
    6. 注意不同操作系统下,库文件的扩展名和路径可能会有所不同。在Linux中,通常使用 .so
      扩展名,而在Windows中使用 .dll
      扩展名。
    6、Makefile?
    Makefile是一种用于构建和管理项目的文本文件,通常用于编译源代码并生成可执行文件、动态库、静态库等。Makefile使用一种特定的语法,其中包含了目标(target)、依赖关系(dependencies)、命令等信息,用于描述如何构建项目的各个组件。
    Makefile的基本结构:
    Makefile由一系列规则(rules)组成,每个规则通常包含以下部分:
    • 目标(target):指定要构建的结果的名称。可以是可执行文件、库文件等。
    • 依赖关系(dependencies):指定构建目标所依赖的文件或其他目标。如果依赖文件发生变化,目标需要重新构建。
    • 命令(commands):描述如何从依赖文件构建目标文件的具体步骤。通常使用TAB键缩进来表示命令。
    一个简单的Makefile示例,用于构建一个名为 myprogram
    的可执行文件:
      myprogram: main.o utils.o
      g++ -o myprogram main.o utils.o


      main.o: main.cpp
      g++ -c main.cpp


      utils.o: utils.cpp
      g++ -c utils.cpp
      Makefile的使用:
      要使用Makefile来构建项目,可以在项目目录中运行以下命令:
        make
        Make工具将自动查找名为 Makefile
        makefile
        的文件,并根据文件中的规则执行构建。如果要构建特定的目标,使用:
          make target_name
          例如,要构建上述示例中的 myprogram
          ,可以运行:
            make myprogram
            变量和条件:
            Makefile还支持变量的定义和条件判断,以便更灵活地管理项目。你可以定义变量来存储编译器选项、源文件列表等信息,并使用条件语句来根据不同情况执行不同的构建步骤。
            示例:
              CC = g++
              CFLAGS = -Wall -O2
              SRC = main.cpp utils.cpp


              myprogram: main.o utils.o
              $(CC) -o myprogram main.o utils.o


              main.o: main.cpp
              $(CC) $(CFLAGS) -c main.cpp


              utils.o: utils.cpp
              $(CC) $(CFLAGS) -c utils.cpp
              7、两个动态库有同样的函数,调用的是哪一个动态库的?(感觉是编译链接的顺序,但是怕不懂装懂还是说了不知道)
              在C++中,如果有两个动态库(例如两个DLL文件)中都包含相同名称的函数,并且你的程序链接了这两个动态库,那么会出现函数冲突的问题。在这种情况下,调用哪一个动态库的函数取决于链接顺序和动态链接器的规则。
              通常情况下,链接器会从左到右按照库的顺序搜索函数,一旦找到第一个匹配的函数,就会停止搜索。这意味着,如果你的程序链接了两个具有相同函数名的动态库,而且第一个库在命令行中出现在第二个库之前,那么程序将调用第一个库中的函数。
              示例:
              假设有两个动态库:libA.dll
              libB.dll
              ,它们都包含一个名为 myFunction
              的函数。
              如果你的编译命令如下:
                g++ -o myprogram myprogram.cpp -L/path/to/libA -lA -L/path/to/libB -lB
                那么 libA.dll
                中的 myFunction
                将被调用,因为它在命令行中出现在 libB.dll
                之前。
                如果你想要调用 libB.dll
                中的 myFunction
                ,可以将链接顺序颠倒:
                  g++ -o myprogram myprogram.cpp -L/path/to/libB -lB -L/path/to/libA -lA
                  这会导致 libB.dll
                  中的 myFunction
                  被调用。
                  要解决这个问题,一种方法是重命名其中一个动态库中的函数,以避免冲突。另一种方法是在链接时使用 -Bsymbolic
                  选项,这将使得在动态库中搜索函数的顺序不受影响,但这种方法可能会引入其他问题,因此需要谨慎使用。
                  总之,动态库中函数的调用顺序取决于链接顺序和动态链接器的规则。为了避免函数冲突问题,建议在设计动态库时使用唯一的函数名,或者使用命名空间来隔离函数。
                  8、问HTTP和TCP的区别?
                  1. 协议层次:
                    1. TCP(传输控制协议):TCP位于 OSI 模型的传输层,负责提供可靠的、面向连接的数据传输。它确保数据可靠地从一个节点传输到另一个节点,处理数据的分段、重传、流控制等问题。
                    2. HTTP(超文本传输协议):HTTP位于 OSI 模型的应用层,是一种用于传输超文本(例如网页)的协议。HTTP依赖于底层的传输协议,通常是TCP,但也可以是其他协议(如HTTP/2使用的是TCP或TLS)。
                  2. 目的和职责:
                    1. TCP:TCP的主要目的是提供端到端的可靠数据传输,确保数据的可靠性和顺序性。它处理数据的分段、重传、流量控制等,但不关心数据的内容。
                    2. HTTP:HTTP的主要目的是在客户端和服务器之间传输和交互超文本资源。它定义了请求-响应模型,允许客户端发送HTTP请求来获取服务器上的资源(例如网页、图像、视频等),并接收服务器的响应。
                  3. 数据格式:
                    1. TCP:TCP传输的是原始二进制数据,没有对数据的结构和语义进行解释。它只关心数据的可靠传输。
                    2. HTTP:HTTP传输的是文本数据,通常使用ASCII字符集编码。HTTP定义了请求和响应的格式,包括请求方法、头部字段、正文等。HTTP的语义规则定义了如何解释这些数据。
                  4. 连接性:
                    1. TCP:TCP是面向连接的协议,它在通信开始前建立连接,然后进行数据传输,最后关闭连接。这种连接需要维护一些状态信息,如源端口、目标端口、序列号等。
                    2. HTTP:HTTP是无状态的协议,每个HTTP请求都是独立的,服务器不会保留关于客户端的状态信息。为了保持状态,HTTP使用机制如Cookie来在请求之间传递状态信息。
                  5. 端口:
                    1. TCP:TCP使用端口来标识不同的服务和应用程序。每个端口都有一个特定的编号,用于将数据传递给正确的应用程序。
                    2. HTTP:HTTP通常使用TCP的80端口(HTTP)或443端口(HTTPS)来进行通信,但可以使用其他端口,只要客户端和服务器都知道。
                  6. 安全性:
                    1. TCP:TCP本身不提供任何安全性保障,数据传输是明文的。但可以通过其他机制(如TLS/SSL)来在TCP上实现安全性。
                    2. HTTP:HTTP也是明文传输的协议,但可以通过使用HTTPS(HTTP Secure)来加密通信内容,提供安全性。
                  9、那HTTP发送的是什么?
                  一种应用层协议,它用于在客户端和服务器之间传输和交互超文本资源,例如网页、图像、音频文件等。
                  发送的主要内容:
                  1. 请求(Request):客户端使用HTTP请求来获取服务器上的资源。HTTP请求通常包括以下信息:
                    1. 请求方法(HTTP Method):定义了客户端的操作类型,如GET、POST、PUT、DELETE等。
                    2. 请求URL(Uniform Resource Locator):指定了要访问的资源的地址。
                    3. 请求头(Request Headers):包含了请求的元信息,如用户代理、接受的内容类型、认证信息等。
                    4. 请求体(Request Body):通常包含了客户端发送给服务器的数据,如表单数据、JSON数据等。在GET请求中,请求体通常为空。
                  2. 响应(Response):服务器使用HTTP响应来回应客户端的请求。HTTP响应通常包括以下信息:
                    1. 状态码(Status Code):用于指示请求的结果状态,如200 OK表示成功,404 Not Found表示资源不存在,500 Internal Server Error表示服务器内部错误等。
                    2. 响应头(Response Headers):包含了响应的元信息,如服务器信息、响应的内容类型、响应时间等。
                    3. 响应体(Response Body):包含了服务器返回给客户端的实际数据,如网页内容、JSON数据等。
                  3. 其他元信息: HTTP还可以传输其他的元信息,如Cookies、缓存控制指令、认证信息等,以控制和管理通信的各个方面。
                  10、HTTP报文有什么内容?(忘了)
                  请求报文(Request):
                  1. 请求行(Request Line):请求行包含了请求的方法、请求的URL和HTTP协议版本。例如:
                    GET /index.html HTTP/1.1
                    1. 请求头部(Request Headers):请求头部包含了关于请求的附加信息,以键值对的形式表示。常见的请求头部包括:
                      1. Host
                        :指定服务器的主机名和端口号。
                      2. User-Agent
                        :包含了客户端的信息,如浏览器类型和版本。
                      3. Accept
                        :指定客户端可接受的响应内容类型。
                      4. Cookie
                        :包含了客户端的会话信息。
                      5. Authorization
                        :用于进行身份验证的信息。
                    2. 空行(Blank Line):空行用于分隔请求头部和请求体,通常只包含一个回车换行符。
                    3. 请求体(Request Body):请求体包含了客户端向服务器发送的数据。这部分在一些请求中可能为空,例如GET请求。在POST请求中,请求体通常包含表单数据、JSON数据或其他内容。
                    响应报文(Response):
                    1. 状态行(Status Line):状态行包含了响应的HTTP协议版本、状态码和状态消息。例如:
                      HTTP/1.1 200 OK
                      1. 响应头部(Response Headers): 响应头部包含了关于响应的附加信息,以键值对的形式表示。常见的响应头部包括:
                        1. Content-Type
                          :指定响应的内容类型,如text/html、application/json等。
                        2. Content-Length
                          :指定响应内容的长度(字节数)。
                        3. Set-Cookie
                          :设置在客户端的Cookie。
                        4. Location
                          :用于重定向,指定新的URL。
                      2. 空行(Blank Line):空行用于分隔响应头部和响应体,通常只包含一个回车换行符。
                      3. 响应体(Response Body): 响应体包含了服务器返回给客户端的数据,例如HTML页面、JSON数据、图片等。
                      11、问哈希表?(不太了解)
                      存储键值对(Key-Value Pairs)并支持高效的插入、删除和查找操作。它通过将键(key)映射到数组的索引来实现这些操作,使得查找的时间复杂度通常为常数时间 O(1)。
                      1. 哈希表的核心是哈希函数,它接受一个键作为输入,然后将该键映射到数组的一个索引位置。这个映射的过程是快速的,通常需要常数时间。哈希函数的设计和性能直接影响了哈希表的性能。
                      2. 哈希表通常由一个数组和一组哈希函数组成。每个数组位置称为“桶”,每个桶可以存储一个或多个键值对。当多个键映射到同一个桶时,通常会使用链表、红黑树等数据结构来解决冲突。
                      3. 哈希冲突:
                        1. 开放地址法(Open Addressing):尝试将键放入其他空闲桶,直到找到一个空桶或遍历完所有桶。
                        2. 链地址法(Chaining):在每个桶中使用链表或其他数据结构存储多个键值对,具有相同哈希值的键都存储在同一个桶中。
                      4. 哈希表的操作
                        1. 插入(Insertion):将一个键值对插入哈希表。
                        2. 查找(Lookup):根据键查找对应的值。
                        3. 删除(Deletion):根据键删除对应的键值对。
                      5. 哈希表的应用
                        1. 数据库中的索引结构。
                        2. 缓存数据的存储。
                        3. 编程语言中的集合和字典数据结构(如Python中的字典)。
                        4. 分布式系统中的数据分片和路由。
                        5. 哈希表还用于密码学中的散列函数,如SHA-256、MD5等。
                      12、哈希表怎么实现的?
                      手动实现哈希表步骤:
                      1. 选择合适的哈希函数:哈希函数应该将关键字映射到一个特定的桶中,最好是均匀地分布在哈希表中。常见的哈希函数有除余法(mod)、乘法散列等。在实现哈希函数时,应该考虑到哈希表的大小和负载因子等因素。
                      2. 选择适当的存储结构:哈希表通常使用数组来实现,每个数组元素对应一个桶,存储与该桶对应的关键字。如果桶中有多个关键字,可以使用链表或二叉搜索树等结构来解决哈希冲突。
                      3. 实现哈希表的基本操作:哈希表的基本操作包括插入、查找和删除。在实现这些操作时,需要先通过哈希函数计算出关键字对应的桶,然后根据具体的存储结构进行操作。
                      示例:
                        #include <iostream>
                        #include <list>
                        using namespace std;


                        class HashTable {
                        private:
                        int tableSize;
                        list<int> *table;


                        int hashFunction(int key) {
                        return key % tableSize;
                        }


                        public:
                        HashTable(int size) {
                        tableSize = size;
                        table = new list<int>[tableSize];
                        }


                        void insert(int key) {
                        int index = hashFunction(key);
                        table[index].push_back(key);
                        }


                        bool search(int key) {
                        int index = hashFunction(key);
                        for (auto it = table[index].begin(); it != table[index].end(); it++) {
                        if (*it == key) {
                        return true;
                        }
                        }
                        return false;
                        }


                        void remove(int key) {
                        int index = hashFunction(key);
                        table[index].remove(key);
                        }


                        ~HashTable() {
                        delete[] table;
                        }
                        };


                        int main() {
                        HashTable ht(7);
                        ht.insert(10);
                        ht.insert(20);
                        ht.insert(15);


                        cout << ht.search(10) << endl; // 输出1,表示存在关键字10
                        cout << ht.search(30) << endl; // 输出0,表示不存在关键字30


                        ht.remove(10);
                        cout << ht.search(10) << endl; // 输出0,表示关键字10已被删除


                        return 0;
                        }

                        14、为什么用哈希表不用链表和数组?
                        1. 快速查找和插入哈希表在查找和插入操作上具有常数时间复杂度 O(1) 的优势,这意味着无论哈希表的大小如何,操作的时间开销都是可接受的。相比之下,链表和数组的查找操作通常需要线性时间复杂度 O(n),其中 n 是元素的数量。
                        2. 空间利用率哈希表通常具有较高的空间利用率。虽然哈希表的大小可能会动态调整以适应元素的增长,但由于哈希函数的作用,它不会像数组一样需要提前分配大块内存。链表通常需要额外的指针来维护节点之间的关系,因此在存储大量元素时可能会浪费一些内存。
                        3. 键值对的关联性哈希表适用于键值对(Key-Value Pairs)的存储和检索。每个键都通过哈希函数映射到一个唯一的位置,因此可以根据键快速找到对应的值。这在许多实际应用中非常有用,如数据库索引、缓存和字典数据结构。
                        但是,链表和数组也有它们的优点和适用场景。例如,链表适用于需要频繁的插入和删除操作的情况,因为在链表中插入和删除节点的时间开销较小。数组适用于元素数量固定或者大小已知的情况,因为它们可以在内存中连续存储元素,具有较好的内存局部性。
                        15、哈希表快还是数组快,为什么?
                        哈希表和数组各有其优点和适用场景,它们的性能快慢取决于具体的操作和使用情境。
                        哈希表的优点:
                        1. 快速查找和插入:哈希表在查找和插入操作上具有常数时间复杂度 O(1) 的性能。这意味着无论哈希表的大小如何,操作的时间开销都是恒定的。
                        2. 适应动态数据:哈希表可以根据数据的动态增长自动扩展,而无需提前分配大块内存。这使得它适用于需要频繁插入和删除的情况。
                        3. 键值对关联:哈希表适用于存储键值对,并能够根据键快速查找对应的值。这在许多应用中非常有用,如数据库索引、缓存、字典数据结构等。
                        数组的优点:
                        1. 直接访问元素:数组具有连续的内存存储,可以通过索引直接访问元素。因此,在已知索引的情况下,访问元素非常快速,具有常数时间复杂度 O(1)。
                        2. 节省内存:数组通常比哈希表占用更少的内存,因为它们不需要额外的指针来维护元素之间的关系。
                        性能比较的考虑因素:
                        1. 查找操作:哈希表通常在查找操作上更快,因为它们使用哈希函数将键映射到索引,而无需遍历整个数组。
                        2. 插入和删除操作:哈希表在动态插入和删除操作上更快,因为数组需要移动元素来维持连续存储。
                        3. 内存占用:数组通常占用更少的内存,因为哈希表需要额外的内存来存储哈希函数的索引和指针。
                        4. 数据访问模式:如果访问模式是随机访问,并且可以通过索引快速定位元素,数组更有优势。如果是根据键进行查找和插入,哈希表更合适。
                        总的来说,哈希表在查找、插入和删除操作上通常更快,特别是在动态数据和大量键值对的情况下。然而,数组在直接访问元素和节省内存方面具有优势。
                        16、场景题1
                          #include <iostream>


                          class A {
                          public:
                          A() {
                          func();
                          }
                          virtual void func() {
                          std::cout << "A::func()" << std::endl;
                          }
                          virtual void test() {
                          func();
                          }
                          };


                          class B : public A {
                          public:
                          B() {
                          func();
                          }
                          virtual void func(){
                          std::cout << "B::func()" << std::endl;
                          }
                          };


                          int main() {
                          B b;
                          b.test();
                          A* a = &b;
                          a->test();
                          return 0;
                          }

                          1. 问b对象调用的是父类的func还是子类的func
                          b 对象调用的是子类 B 的 func()。这是因为在 B 类中重写了虚拟函数 func(),并且在 B 类的构造函数中调用了 func()。所以,当创建 B 对象 b 时,首先调用 B 类构造函数,该构造函数调用了 B 类的 func()。
                          1. 问b.test调用的是父类的func还是子类的func
                          b.test()
                          调用的是子类 B
                          func()
                          。虽然 test()
                          函数在父类 A
                          中声明,但由于在子类 B
                          中重写了虚拟函数 func()
                          ,在 test()
                          函数中调用的是子类 B
                          的版本。
                          1. 问a->test调用的是父类的func还是子类的func
                          a->test()
                          调用的是子类 B
                          func()
                          。虽然 a
                          是一个指向父类 A
                          的指针,但在运行时它指向的是子类 B
                          的对象。因此,调用 a->test()
                          时会根据对象的实际类型调用子类 B
                          的版本。
                          17、场景题2:
                            class B {
                            virtual void funcB(){};
                            };
                            class C {
                            virtual void funcC(){};
                            }
                            class A : public B, public C {
                            virtual void funcB(){};
                            virtual void funcC(){};
                            };
                            void func() {
                            A* a = new A();
                            B* b = a;
                            C* c = a;
                            }

                            这段代码中,如A类多继承B类、C类,实例化A对象,赋值给B、C指针,A、B、C地址数值上有什么区别?
                            1. A* a = new A();
                              创建了一个 A
                              类的对象,并将指针 a
                              指向该对象。
                            2. B* b = a;
                              创建了一个 B*
                              类型的指针 b
                              ,并将 a
                              指向的 A
                              对象的地址赋值给了 b
                              。这实际上是将 A
                              对象的地址视为 B
                              类型的指针。
                            3. C* c = a;
                              创建了一个 C*
                              类型的指针 c
                              ,并将 a
                              指向的 A
                              对象的地址赋值给了 c
                              。同样,这实际上是将 A
                              对象的地址视为 C
                              类型的指针。
                            这种情况下,虽然 A
                            类对象 a
                            的地址与 B
                            类指针 b
                            C
                            类指针 c
                            的地址是相同的,但在类型系统中,它们是不同的类型。这也就意味着:
                            1. b
                              指针的静态类型是 B*
                              ,因此你可以使用 b
                              指针访问 B
                              类中的成员函数和数据成员,但不能访问 C
                              类的成员。
                            2. 同样,c
                              指针的静态类型是 C*
                              ,因此你可以使用 c
                              指针访问 C
                              类中的成员函数和数据成员,但不能访问 B
                              类的成员。
                            3. a
                              指针的静态类型是 A*
                              ,因此你可以使用 a
                              指针访问 A
                              类、B
                              类和 C
                              类中的成员函数和数据成员,因为 A
                              类同时继承了 B
                              类和 C
                              类的成员。
                            18、场景题3:
                              事务隔离级别
                              SELECT a FROM tbl1 WHERE id = 1; a = 1000
                              事务1
                              BEGIN;
                              UPDATE tbl1 SET a = a + 200 WHERE id = 1;
                              COMMIT;


                              事务2
                              BEGIN;
                              SELECT a FROM tbl1 WHERE id = 1;
                              ......
                              SELECT a FROM tbl1 WHERE id = 1;
                              COMMIT;

                              事务隔离级别定义了多个事务之间的可见性和互相影响的程度。
                              常见的隔离级别有四种,分别是:读未提交(Read Uncommitted)、读提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。
                              读未提交(Read Uncommitted):
                              • 事务1修改数据并提交,但未提交前,事务2可以读取到事务1的未提交的修改。这意味着事务2可以看到脏数据(未提交的数据)。
                              • 在上述示例中,事务2可以在事务1修改并提交之前读取到修改的结果。
                              读提交(Read Committed):
                              • 事务1修改数据并提交后,事务2才能读取到事务1的修改。这保证了已提交的数据对其他事务可见。
                              • 在上述示例中,事务2只能在事务1提交后才能读取到修改的结果。
                              可重复读(Repeatable Read):
                              • 事务1修改数据并提交后,事务2仍然看不到事务1的修改,直到事务2自身提交。这保证了事务2在整个事务过程中看到一致的数据状态,但在事务2提交之前,会出现不可重复读(同一数据在不同时间点读取结果不同)的情况。
                              • 在上述示例中,事务2只有在自身提交后才能读取到修改的结果,从而避免了脏读和不可重复读。
                              串行化(Serializable):
                              • 串行化是最高隔离级别,确保事务之间完全隔离,不会发生并发冲突。在串行化隔离级别下,事务1修改数据并提交后,事务2只能在事务1完成后才能执行。
                              • 在上述示例中,事务2只有在事务1完成(包括提交)后才能执行,从而避免了脏读、不可重复读和幻读(事务2查询到了事务1未提交的新增数据)。
                              但是需要注意的是,隔离级别越高,系统的并发性能越低,因为隔离级别高意味着更多的锁和资源占用,导致了更多的阻塞和等待。因此,在选择隔离级别时,需要权衡数据一致性和性能之间的权衡。
                              总结:
                              • 读未提交:允许脏读、不可重复读、幻读。
                              • 读提交:允许不可重复读和幻读,但不允许脏读。
                              • 可重复读:允许幻读,但不允许脏读和不可重复读。
                              • 串行化:最高级别,不允许任何并发问题,但性能最差。
                              应该还有一些其他的,想不起来了
                              问如果让你转语言,比如c++换到go,该怎么学习
                              问有什么比较倾向的技术发展方向
                              问项目里有遇到什么困难吗,怎么解决的
                              最后反问

                              以上便是这个小伙伴的相关面经题目,我也给我一些参考答案,大家可以参考,如果有不合适的地方,还请你们能够给我改错的机会。

                              最后,阿Q新建了一个学习交流群,人虽然不多,但都是想努力上进的小伙伴,感兴趣可免费进,我们一起进步!!


                              文章转载自阿Q正砖,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                              评论