校招面试精选「美团」

前言

        你好,我是小莱,最近秋招已经开始了,有的人一边实习一边交实验报告一边准备秋招,如此高强度下面试结果往往不如人意,但关键还是要稳住心态,做好每一次面试的复盘,查漏补缺。我整理了最近的面试经历,这次精选的面试题以计算机基础知识为主,算法题比较简单。

知识点

1. 进程通信的方式有哪些,平时用过吗?

  • 管道(Pipes):

    • 概念:管道是一种半双工的通信方式,它允许一个进程将数据传递给另一个进程。管道有两种类型:匿名管道和命名管道。匿名管道只能用于父子进程之间的通信,命名管道可以用于任何两个进程之间。与匿名管道不同,命名管道在文件系统中被创建为一个特殊的文件,它的生命周期不依赖于进程,可以随时被不同的进程用于读写数据。

    • 实际应用:在类Unix系统中的管道符|就是使用匿名管道的例子。下面这行命令将 ps 生成的详细进程信息传递给 grep,输出与 processname 相关的信息条目。

    ps -ef|grep processname
  • 信号(Signals):

    • 概念:信号是一种用于通知进程发生某个事件的机制。信号是一种异步的、较为简单的通信方式,用于传递控制信息,如中断、终止等。

    • 实际应用:在Linux系统中,kill -l命令可以查看所有信号。当我们用 Ctrl C 终止一个进程的时候,就是通过操作系统内核传递一个信号给目标进程,进程根据其信号处理函数终止了自己。

  • 信号量(Semaphores):

    • 概念:信号量是一种用于控制对共享资源访问的同步机制。信号量通常用于进程间的互斥和协调,防止资源竞争和死锁。

    • 实际应用:在多进程编程中,信号量可以用于实现互斥锁。例如,生产者-消费者问题中,可以使用信号量来控制缓冲区的访问,确保生产者和消费者不会同时访问缓冲区。

  • 消息队列(Message Queues):

    • 概念:消息队列是一种先进先出(FIFO)的数据结构,允许进程之间通过队列传递消息。消息队列可以实现异步通信,允许进程将消息放入队列中,接收方可以在稍后时间读取消息。更适合需要异步、复杂消息处理和任务调度的场景。

    • 实际应用:在一个分布式系统中,应用程序可以使用消息队列(如RabbitMQ、Kafka)来实现不同服务之间的异步通信和任务调度。

  • 共享内存(Shared Memory):

    • 概念:共享内存允许多个进程访问同一块内存区域,以便快速地交换数据。共享内存是最快的IPC机制,但需要适当的同步机制以避免数据竞争。

    • 实际应用:在数据处理应用中,例如大规模数据分析,多个进程可以使用共享内存区域来存储中间结果,以加速数据处理过程。

  • 套接字(Sockets):

    • 概念:套接字是一种网络通信机制,用于在不同主机或同一主机上的不同进程之间传输数据。Socket 可以选择不同的网络协议(如TCP、UDP)进行通信。

    • 实际应用:在网络应用中,Web服务器(如Apache)通过 Socket 与客户端(如浏览器)进行通信。访问一个网站时,浏览器与服务器之间的数据传输通常是通过 Socket 实现的。

2. 线程在用户态和内核态之间有哪些映射方式,有什么区别?

1. 一对一模型(1:1)

        一个用户级线程直接映射到一个内核级线程。

  • 最大线程数量受到内核数量的限制;
  • 大部分操作都会映射到内核线程上,引起用户态和内核态的频繁切换,增加开销。
2. 多对一模型(N:1)

        多个用户级线程映射到一个内核级线程。

  • 很多操作在用户态就可以完成,减少了内核上下文切换的开销,有点像协程;
  • 线程数量不受限制;
  • 一个线程的阻塞会影响到所有线程。
3. 多对多模型(N:M)

        多个用户级线程动态映射到多个内核级线程。

  • 代码写了多线程实际可能并发也可能并行,两边都在调度,增加复杂性不确定性,操作系统内核一般不用这个。
  • 理论上可以最大限度地利用多核处理器的并行计算能力。

3. 死锁的产生原因,有什么好的解决方式?

原因

        多个线程或进程循环等待对方持有的资源导致都无法正常运行。

解决方式
  • 预防死锁

    • 破坏互斥条件:允许资源被多个进程共享。

    • 破坏占有和等待条件:要求进程在请求任何资源之前,释放所有已经占有的资源。

    • 破坏不可抢占条件:允许资源被抢占。

    • 破坏循环等待条件:通过资源排序算法,确保每个进程按顺序请求资源。

  • 避免死锁

    • 银行家算法:记录系统资源和进程状态,包括资源总量、进程的最大需求、已分配资源等,当进程请求资源时,先进行安全性检查,即当前空闲资源能否满足其要求,如果够让它运行才分配。

4. 单例模式的实现方式,需要考虑哪些细节?

  • 私有构造函数:为了防止外部通过 new 关键字创建类的实例,单例类的构造函数应该是私有的,并且要禁止拷贝构造函数和赋值操作符。

  • 静态实例变量:单例类需要用静态变量来持有唯一的实例,静态变量需要在类外初始化否则编译报错。

  • 公有访问方法:提供一个公有的静态方法,如 getInstance(),用于获取唯一的实例。这个方法需要检查实例是否已经创建,如果没有,则创建它;如果已经创建,则返回该实例。

  • 线程安全:在多线程环境中,需要确保单例的实例化过程、静态变量的写过程是线程安全的。可以通过同步机制来实现,但这可能会影响性能。有多种方法可以确保线程安全,如使用同步锁、双重检查锁定模式(回头拎出来多线程部分单独讲)等。

  • 延迟初始化:就是懒汉模式,不用的时候可以节省资源。

代码示例:

#include <iostream>
#include <mutex>

class Singleton {
private:
    // 私有静态指针变量,指向类的唯一实例
    static Singleton* instance;
    // 用于同步的互斥锁
    static std::mutex mutex;

    // 私有构造函数,防止外部直接创建实例
    Singleton() {
        // 初始化代码...
    }

    // 禁止拷贝构造函数和赋值操作符,防止复制实例
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

public:
    // 公有静态方法,提供全局访问点
    static Singleton* getInstance() {
        // 双重检查锁定模式(Double-Check Locking)
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mutex);
            if (instance == nullptr) {
                instance = new Singleton();
            }
        }
        return instance;
    }

    // 示例方法
    void doSomething() {
        std::cout << "Doing something..." << std::endl;
    }
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

int main() {
    // 获取单例对象并调用其方法
    Singleton* singleton = Singleton::getInstance();
    singleton->doSomething();

    return 0;
}

5. http 和 https 有什么区别?

  • HTTPS在HTTP的基础上加入了SSL/TLS协议,提供了数据加密、完整性校验和身份验证。

  • 协议过程简述:客户端请求证书,服务器返回证书,客户端使用证书中的公钥加密一个随机数发给服务端,服务端用私钥解密得到随机数,双方基于随机数派生一个会话密钥进行加密通讯。

6. 手撕算法:删除倒数第n个链表节点。

  • 遍历一遍确定链表长度,再定位去删节点,虚拟头结点处理边界情况。

删除倒数第n个链表节点 - 力扣(LeetCode)

" Simplicity is the soul of efficiency. "


The End

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值