可行但需优化:插入时记录绝对过期时间(steady_clock::time_point),get时仅比较,避免高频调用now();禁用system_clock;读多写少用shared_mutex,高并发可分段加锁;过期清理宜折中——写入时顺带扫描少量bucket。

缓存容器要不要自己实现 std::chrono 时间判断?
直接用 std::chrono 做过期判断是可行的,但别在每次 get() 时都调用 std::chrono::steady_clock::now() —— 高频访问下它可能成为瓶颈。更稳妥的做法是:插入/更新时记录绝对过期时间(std::chrono::time_point),get() 时只做一次比较。注意别用 system_clock,它可能因系统时间调整导致误判过期。
std::unordered_map 加锁怎么避免性能暴跌?
单个 std::shared_mutex(C++17)比 std::mutex 更适合读多写少场景;但如果缓存项极多且并发读压力大,按 key 分段加锁(比如对 hash 值取模分桶)能显著降低争抢。别用全局锁配 std::map —— 红黑树遍历本身就有开销,再加锁会放大延迟。示例中常见错误是:在持有写锁期间调用用户回调(如淘汰回调),导致锁持有时间不可控。
过期项是懒删除还是定时清理?
懒删除(访问时检查并丢弃)实现简单、无后台线程干扰,但可能导致内存持续增长;定时清理需额外线程 + 条件变量,容易引发唤醒抖动或清理不及时。折中方案:在每次写入时,顺带扫描少量(如 16 个)随机 bucket 中的过期项并清理。这样既不依赖定时器,又防止过期项堆积。注意别在清理时重新哈希整个 map —— erase(iterator) 是 O(1) 平摊,但批量 erase 还是得小心迭代器失效。
如何让缓存支持自定义过期策略(比如 LRU + TTL)?
纯 TTL 缓存只需时间戳字段;若要叠加 LRU,就得维护访问顺序链表或用 std::list + std::unordered_map 组合。但要注意:TTL 判断必须独立于 LRU 排序逻辑,否则“最近访问”可能让已过期项被错误保留在头部。更实际的做法是把过期判断下沉到 get() 和 put() 入口,LRU 只负责排序未过期项。另外,别把过期时间存在 value 里 —— 应该和 key 绑定存在缓存节点结构体中,否则序列化或拷贝时容易丢失时效信息。
立即学习“C++免费学习笔记(深入)”;
真正难的不是记时间,而是让过期判断不拖慢热路径,也不让清理逻辑破坏并发安全。多数人栽在锁粒度和清理时机上,而不是时间计算本身。


















