淘天 客户端开发-C++ 一面
1. 自我介绍
2. 你为什么做这个项目
3. 你在项目中有遇到什么困难吗?
4. 这个项目是买的博主的还是学校让做的
5. 项目中有用到线程池吗?线程池的核心结构是什么?
项目中使用了线程池处理服务端异步业务逻辑,避免阻塞IO线程。核心结构包括:任务队列、工作线程组、互斥锁(保证队列安全)、条件变量(线程等待与唤醒)、任务提交与调度接口。
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
using namespace std;
class ThreadPool {
public:
ThreadPool(int num = 4) : stop(false) {
for (int i = 0; i < num; ++i)
threads.emplace_back([this] { run(); });
}
template<class F>
void addTask(F&& f) {
unique_lock<mutex> lock(mtx);
tasks.emplace(forward<F>(f));
cv.notify_one();
}
~ThreadPool() {
stop = true;
cv.notify_all();
for (auto& t : threads) t.join();
}
private:
void run() {
while (true) {
unique_lock<mutex> lock(mtx);
cv.wait(lock, [this] { return stop || !tasks.empty(); });
if (stop && tasks.empty()) return;
auto task = move(tasks.front());
tasks.pop();
lock.unlock();
task();
}
}
vector<thread> threads;
queue<function<void()>> tasks;
mutex mtx;
condition_variable cv;
bool stop;
};
6. RPC 服务端收到消息时会有异步处理,这部分你是怎么设计的?
服务端采用IO线程与工作线程分离的设计:
- IO线程仅负责接收数据、拆包、协议解析;
- 将解析完成的请求封装为任务对象;
- 提交至线程池异步执行业务逻辑;
- 处理完成后,将响应结果交还给IO线程发送回客户端。该设计保证IO线程不被耗时逻辑阻塞,提升系统并发能力。
7. 项目底层使用什么协议通信?为什么选用 TCP?
底层采用TCP协议通信。RPC调用要求消息可靠、有序、不丢失、不重复,TCP原生支持连接管理、确认应答、超时重传、流量控制和拥塞控制,能保证远程调用的稳定性和正确性,非常适合RPC这种强可靠性要求的场景。
8. 如果换成 UDP 可以吗?上层需要做哪些设计来保证可靠性?
UDP可以使用,但UDP本身不可靠,必须在应用层实现可靠性机制:
- 消息编号与序列号;
- ACK确认应答机制;
- 超时重传策略;
- 乱序数据包重排;
- 重复数据包过滤;
- 基础拥塞控制。相当于在应用层实现一套轻量级TCP可靠性协议。
9. 你了解 muduo 库的底层实现模型吗?
muduo采用one loop per thread + 线程池的经典高并发模型:
- 基于epoll事件驱动,非阻塞IO;
- 每个线程拥有独立的事件循环loop;
- IO线程只处理网络事件,不执行业务逻辑;
- 耗时业务交由线程池异步处理;整体无锁设计、低延迟、高并发,是客户端/服务端网络层的优秀实现方案。
10. 你的项目主体只有 RPC 客
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
C++ 常考面试题总结 文章被收录于专栏
本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.



查看10道真题和解析