You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

我的C#带元素过期功能的TokenCache实现是否线程安全?

你的TokenCache实现问题分析

1. 当前实现的直接问题

  • 重复添加同一key会导致提前过期:每次调用Add同一key时,都会生成一个新的过期删除任务。比如第一次添加key后,过了一半时间再次添加该key,旧的过期任务仍会在原定时时间执行Remove,把刚添加的新值删掉,导致新值没到设定时间就被移除。
  • 线程池资源浪费:用Task.Run(() => Thread.Sleep(expirationTime))会占用线程池线程,大量添加元素时会消耗线程池资源,影响其他依赖线程池的操作性能。
  • 异常被静默忽略:过期任务的ContinueWith没有处理异常,一旦Remove过程中出现异常(比如信号量异常),异常会被吞掉,难以排查问题。
  • 过期时间不精确:Thread.Sleep的实际等待时间受线程调度影响,会比设定的expirationTime偏长,导致过期时间不准。

2. 是否属于开箱即用的线程安全实现?

答案是不能完全算,理由如下:

  • 过期任务的并发冲突:同一key的多个过期任务会重复执行Remove,如果两次Remove之间有其他线程重新添加了该key,后续的Remove会错误删除刚添加的有效数据。
  • 缺少资源释放机制:SemaphoreSlim实现了IDisposable接口,但你的类没有实现IDisposable,长时间运行会导致信号量资源泄漏。
  • 未保护存储对象的线程安全:GetValueOrDefault返回的TValue如果是可变类型,外部线程可以直接修改该对象,而你的类只保护了字典的结构访问,没有对存储对象本身做线程安全防护。

优化建议(可选)

  • 给每个缓存项存储过期时间戳,用Timer定期扫描字典移除过期项,避免大量线程池任务。
  • 重复添加key时,更新对应项的过期时间戳,而不是生成新任务。
  • 实现IDisposable接口,释放SemaphoreSlim和Timer等资源。
  • 如果需要保护TValue的线程安全,可考虑存储不可变对象,或在返回时提供对象副本(若适用)。

内容的提问来源于stack exchange,提问作者Resnick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 22:55:17