这是一道 TikTok 面试中出现的系统设计 / Coding Design 类题目。题目看起来只有一句话,但实际上同时覆盖了并发控制、任务调度、缓存、取消机制以及事件通知,需要候选人在较短时间内快速拆解需求,并给出一个能够实际落地的设计。
英文原题
Design a thread-safe resource manager that prioritizes, loads, cancels, caches, and notifies multiple component requests efficiently under high concurrency.
设计一个线程安全的资源管理器,在高并发环境下,高效处理多个组件发起的资源请求,并支持优先级、加载、取消、缓存以及通知。
这道题真正考什么?
这类题最容易犯的错误,是看到 thread-safe 就立刻开始加 Lock。
实际上,锁只是其中很小的一部分。
面试官真正想看的,是候选人能不能先把整个系统拆成几个清晰的职责:
Request → Scheduling → Loading → Cache → Notification
例如,不同 Component 可能同时请求同一个 Resource:
Component A ──┐
Component B ──┼──> Resource Manager ──> Loader
Component C ──┘这时候就会出现第一个关键问题:
如果 A、B、C 请求的是同一个资源,是否真的需要启动三次加载?
显然不应该。
一个比较合理的设计,是维护一个 in-flight request registry。
第一次请求到来时创建真正的加载任务,后续相同资源的请求只需要注册成为 subscriber:
Resource X
A ──┐
B ──┼──> One Loading Task
C ──┘加载完成以后,再统一通知所有仍然有效的调用方。
Priority 怎么处理?
题目中特别强调了 prioritizes。
因此简单的 FIFO Queue 通常不够。
可以考虑:
Priority Queue
↓
Worker Pool
↓
Resource Loader例如:
HIGH UI 当前立即需要
MEDIUM 即将展示
LOW PrefetchScheduler 根据 priority 选择下一个任务。
但是这里还有一个面试中很值得讨论的问题:
如果一个 LOW priority 的资源正在等待,此时另一个 Component 对同一个资源发出了 HIGH priority 请求怎么办?
好的设计不应该创建第二个任务,而应该考虑将已有任务的 effective priority 提升。
这也是这道题从普通 Coding 题进入系统设计思维的地方。
Cancel 并不是简单删除任务
取消也是这道题非常容易踩坑的部分。
假设:
A ──┐
B ──┼──> Resource X
C ──┘现在 A cancel 了请求。
这并不代表 Resource X 的加载应该被取消,因为 B 和 C 仍然需要这个资源。
因此 Cancel 更合理的粒度是:
取消 subscriber,而不是直接取消 shared loading task。
只有当:
subscriber count == 0并且加载任务本身允许取消时,才真正停止底层资源加载。
否则一个 Component 的取消操作可能会影响其他 Component。
Cache 又带来了新的并发问题
Resource Manager 一般还会维护 Cache:
Request
↓
Cache Hit? ── Yes ──> Return
│
No
↓
Check In-flight Request
↓
Schedule Loading这里至少需要考虑:
- 多线程同时读取 Cache
- Cache miss 后重复创建任务
- Cache eviction
- Resource loading 完成与 cancel 同时发生
- Cache update 和 subscriber notification 的顺序
所以这道题真正困难的地方,并不是写一个 Dictionary,而是保证整个状态转换在并发情况下仍然一致。
Notification 怎么设计?
资源加载完成以后,还需要通知所有请求它的 Component。
这里通常可以设计成 callback / future / promise / event listener。
例如:
Resource Loaded
↓
Update Cache
↓
Remove In-flight Task
↓
Notify Subscribers同时还要注意:
不要在持有核心 Lock 的情况下执行用户 callback。
因为 callback 本身可能:
- 执行很慢
- 再次请求 Resource Manager
- acquire 其他 lock
- 触发新的 callback
如果直接在锁内部执行,很容易造成严重的 contention,甚至 deadlock。
更安全的方式通常是:
先在锁内更新共享状态并复制 subscriber 列表,然后释放锁,再执行 notification。
面试中最值得讲清楚的几个点
这道题如果只写出一个能运行的 ResourceManager,通常还不够。
真正拉开差距的是候选人能不能主动讨论:
同一资源请求如何去重
Priority 是否可以动态提升
多个 subscriber 中一个取消怎么办
什么时候真正取消底层加载
Cache 和 in-flight request 如何保证原子性
Callback 是否可以在 Lock 内执行
高并发下如何减少锁竞争
异常加载之后如何通知多个调用方
这些才是面试官继续追问的地方。
这种题的难点,也正是技术面试里最容易出现的情况:
题目本身不长,但隐藏条件很多。
候选人不仅要写代码,还要一边和面试官沟通,一边判断:
面试官现在更关心线程安全吗?
还是 Priority Queue?
还是取消语义?
为什么突然开始追问 cache?
下一步应该先写代码还是先解释架构?
这也是 csoahelp 实时文本面试辅助比较适合发挥作用的场景。
我们可以在面试过程中根据面试官的问题实时分析当前考察点,帮助候选人快速整理:
需求拆解 → 数据结构 → 并发模型 → Edge Case → Follow-up
特别是这种 System Design + Coding 混合题,很多时候并不是候选人完全不会,而是现场几十秒内很难把所有并发场景同时考虑完整。
除了正式面试中的实时文本辅助,我们也提供 Mock Interview,可以针对 TikTok、Google、Meta、Amazon 等公司的 Coding / System Design 风格提前模拟追问,把这种「第一问很简单,后面不断加条件」的面试节奏提前练熟。
我们也有代面试,面试辅助,OA代写等服务助您早日上岸~
