← 中文资源

简体中文版本

带容量与命中统计的 LRU 缓存

基于 OrderedDict 实现线程安全的 LRU 缓存,支持容量淘汰、命中率统计,并提供保持函数签名的 memoize 装饰器。

阅读英文原文

功能说明

LRUCache 用 OrderedDict 保存键值,读取命中时把键移到末尾,写入后如果超过容量就淘汰最前面的条目。所有操作由 RLock 保护,适合多线程共享。memoize 装饰器把单参数函数包成缓存查询:先查缓存,未命中再计算并写回,同时保留原函数元数据。

关键代码

def get(self, key: K) -> V | None:
    with self._lock:
        if key not in self._items:
            self.misses += 1
            return None
        self.hits += 1
        self._items.move_to_end(key)
        return self._items[key]

move_to_end 是 O(1) 操作,这是选择 OrderedDict 而不是普通字典加列表的原因。

使用注意

  • 缓存值为 None 时会被当成未命中,memoize 不适合返回 None 的函数;可改用哨兵对象区分。
  • 只支持可哈希的键,示例装饰器限制为单参数,多参数需要把参数元组作为键。
  • 没有过期时间,数据永久有效;需要 TTL 时应记录写入时间并在读取时检查。
  • stats() 的命中率是累计值,不会自动重置。
  • 缓存不保证并发计算的去重,两个线程可能同时未命中并重复计算。

验证方式

示例容量为 2:连续访问 4 两次只计算一次,再访问 5、6 会把 4 淘汰,最后再访问 4 会重新计算。输出中的 calls 应为 4,stats 显示大小、命中、未命中和命中率。