字节跳动-后端开发实习生-C++ 一面

1. 自我介绍

2. 项目介绍

3. 进程和线程的本质区别是什么,为什么线程切换通常更轻

答案:进程是资源分配的基本单位,线程是 CPU 调度的基本单位。一个进程有自己独立的虚拟地址空间、文件描述符表、页表等资源;同一进程里的多个线程共享代码段、数据段、堆、打开的文件等资源,但每个线程有自己独立的栈、寄存器上下文和线程局部存储。线程切换通常比进程切换轻,是因为同进程线程切换时,不需要像进程切换那样频繁切换地址空间和页表,缓存和 TLB 的破坏通常也更小。但“轻”不代表没成本,线程切换依然涉及内核调度、寄存器保存恢复、可能的锁竞争和缓存失效。

4. 进程通信方式有哪些,怎么选

答案:常见的进程通信方式有管道、命名管道、消息队列、共享内存、信号、套接字、信号量、内存映射文件。如果是父子进程、数据量不大、单向流式通信,管道足够;如果是本机高吞吐、低拷贝场景,共享内存更合适;如果需要跨机器,通常还是 socket;如果更关注消息边界和异步解耦,可以考虑消息队列。共享内存性能高,但同步复杂;消息队列使用方便,但吞吐和延迟通常不如共享内存;socket 通用性最好,代价是协议处理和拷贝链路更长。工程里选型一般不会只看“最快”,还要看可维护性、可靠性和故障恢复难度。

5. 线程之间共享哪些内存,真正的问题为什么是可见性和同步

答案:同一进程里的线程共享代码段、全局变量、静态变量、堆内存、文件描述符等资源。但每个线程的栈空间、寄存器和线程局部存储是独立的,所以局部变量通常不会天然共享。面试里问“线程是否有共享内存”,更准确的说法应该是:线程运行在同一个进程地址空间里,天然共享进程级资源,但共享不等于安全。真正麻烦的点在于数据竞争、内存可见性和执行顺序。一个线程改了某个共享变量,另一个线程什么时候看见、看见的是不是中间状态,都需要同步原语来保证。

代码:

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;

atomic<int> ready{0};
int data = 0;

void writer() {
    data = 42;
    ready.store(1, memory_order_release);
}

void reader() {
    while (ready.load(memory_order_acquire) == 0) {}
    cout << data << endl;
}

int main() {
    thread t1(writer), t2(reader);
    t1.join();
    t2.join();
    return 0;
}

6. 用户态和内核态的区别是什么,为什么要区分

答案:用户态和内核态的核心区别在于权限级别不同。用户态程序权限受限,不能直接操作硬件、页表、中断和敏感系统资源;内核态拥有更高权限,可以访问设备、调度进程、管理内存、处理系统调用。之所以要区分,是为了安全性和稳定性。应用程序如果都能直接操作硬件或系统关键资源,任何一个 bug 都可能把整个系统拖垮。应用从用户态切到内核态,一般通过系统调用、异常或中断完成,这个切换本身也有成本,所以高性能场景里会尽量减少不必要的系统调用。

7. 栈和堆的生命周期有什么区别,栈在什么情况下销毁

答案:栈上的对象通常跟随作用域或函数调用生命周期存在,进入作用域时分配,离开作用域时自动释放;堆上的对象由程序员或资源管理对象显式控制,生命周期更灵活。栈的回收通常不需要逐块管理,函数返回时栈帧整体弹出,所以效率高;堆内存则由分配器管理,适合动态大小和跨作用域对象。面试里说“栈什么时候销毁”,更准确地讲,是某个栈帧在函数返回、线程退出或者异常展开离开作用域时被回收。如果是线程栈,那会在线程结束时整体释放;如果是某个函数里的局部对象,会在离开该函数或作用域时析构。

8. 虚拟内存和页表你怎么理解,它和进程隔离有什么关系

答案:每个进程看到的地址空间通常是连续、独立的虚拟地址空间,但真实内存是物理内存。页表的作用是建立虚拟地址到物理地址的映射,CPU 访问内存时会先做地址翻译。进程隔离本质上依赖的是不同进程拥有不同的页表映射,同样的虚拟地址在不同进程里可以映射到完全不同的物理页。这样一个进程默认不能直接访问另一个进程的地址空间,除非通过共享内存、内核映射或特权机制建立共享关系。这也是为什么进程切换比线程切换重,因为进程切换通常伴随地址空间切换。

9. MySQL 事务你了解吗

答案:事务本质上是一组操作,要么全部成功,要么全部失败回滚。MySQL 里事务常说 ACID,分别是原子性、一致性、隔离性、持久性。原子性一般依赖 undo log,一致性是事务执行前后数据状态满足约束,隔离性通过锁和 MVCC 保证,持久性则依赖 redo log。在实际业务里,事务最常见的价值是保证跨多条 SQL 的一致更新,比如扣库存、写订单、更新状态这些动作必须作为一个整体成功。

10. MySQL 的隔离级别和 MVCC 是怎么配合的

答案:MySQL 常见隔离级别有读未提交、读已提交、可重复读和串行化。InnoDB 默认是可重复读,它通过 MVCC 和锁共同实现事务隔离。MVCC 的核心思想是“读历史版本”,普通一致性读不一定加锁,而是结合 undo log 和 Read View 去判断当前事务能看到哪个版本的数据。这样能降低读写冲突,提高并发性能。但如果是当前读,比如 select ... for updateupdatedelete,还是会加锁。面试里如果继续追,通常会问幻读、间隙锁、next-key lock 这些。

11. 进程切换和线程切换的开销主要来自哪里

答案:切换开销主要来自上下文保存恢复、调度器参与、缓存失效和可能的地址空间切换。线程切换时需要保存寄存器、程序计数器、栈指针等上下文;如果跨 CPU 核,还会带来缓存局部性破坏。进程切换除了这些,还经常涉及页表切换、TLB 刷新或部分失效,因此通常更重。真正影响性能的很多时候不是“切没切”,而是切换频率太高,比如线程数失控、锁竞争激烈、任务过细导致调度成本高于执行成本。

12. 常见的死锁场景有哪些,如何避免

答案:最典型的死锁场景是两个线程拿锁顺序相反:线程 A 先拿锁 1 再等锁 2,线程 B 先拿锁 2 再等锁 1。除此之外,递归调用中重复拿非递归锁、持锁等待外部回调、多个模块间锁顺序不统一,也很容易出问题。避免死锁最有效的方法通常是统一加锁顺序、减少锁粒度、避免锁嵌套、使用 std::lock 或层级锁设计。如果线上已经卡住,一般会通过线程栈、锁等待信息、core dump 来定位是谁在相互等待。

代码:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

mutex m1, m2;

void work1() {
    lock(m1, m2);
    lock

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

C++ 常考面试题总结 文章被收录于专栏

本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.

全部评论

相关推荐

从一月份开始准备项目,到不断地整理简历背诵八股,整理面经。学习牛客等平台面试经验,刷Leetcode,CodeTop,再到开学后不断的投递简历,不断地面试/笔试。终于在这一周结束了所有的流程,恭喜自己,也感谢字节的收留,终于终于。我的实习春招告一段落,有了去处。给字节的效率点一个大大的赞,也给字节的面试官点一个大大的赞!速度真的很快,每次也真的可以学到很多!先讲一下个人整个的流程吧二月底的时候在BOSS直聘上被字节HR直接打电话邀请面试,但是那会儿由于个人觉得自己的准备状况还不足以支撑大厂,而且Leetcode和八股什么的还没有背得很充分,所以拒绝了。过了一周到两周后,字节的另外一个部门的差说他的同事把我的简历给了,他邀请我面试个人觉得准备的已经差不多了,便约了几天后进行面试。✅3月18日一面&nbsp;第二天约二面✅3月20日二面&nbsp;三十分钟约三面✅3月24日三面&nbsp;第二天约HR面✅3月25日HR面✅3月27&nbsp;OC+offer+背调由于非常感谢这一次面试。也是为了遵循规定。遵守面试承诺。所以这边的面经就不详细展开发了,简单地说一下每一轮面试的侧重点,第一轮面试面试官非常好,侧重基础,并且耐心的询问每个八股底层和个人的知识边界。大概了解了我的每个项目的构成,第二轮面试官非常的友善平和,着重的和我聊了很多项目的细节,并且拓申到了真实的业务场景里,整体来说都是非常好的场景问题,也给了我很多思考,并且给了很多有用的建议,比如我们常用一些组件为什么要这样用。它的底层原理,让我着重地回去深入了解,整体来说学习到了很多。三面的话就主要的是聊一些其他的问题。Hr面就是简单谈谈说规划和入职这些。最后和牛友们分享下个人的准备,希望能帮到有需要的人:项目方面:点评+全栈Agent(自己的原创项目)刷题算法:LeetCode&nbsp;Hot100*3,着重刷了下CodeTop前两页,自己整理了一份易错的反复刷八股方面:自己整理了Hot100,着重背了这些,没有完全看小林Coding,然后是一些Agent八股,也是自己整理的。其他准备:面试回答的话术,包括每一次面试完,希望友友们养成复盘的习惯,感觉这个很有帮助。大概就是这么多,目前已经准备拒绝剩下的笔试/面试了,感谢字节的收留,也不留二心了,双向奔赴哈哈哈。希望各位UU加油,早日收获心仪的offer!ps:xhs,mt我恨你们,简历都给我直接筛了。我去字节不会想你们的!
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务