创建一次性对象的线程安全缓存



我必须创建一次性对象的线程安全缓存。我怎么看:

  1. 我有一些数据类,我想缓存,例如MyData
  2. 我正在为MyData创建一些集合(例如ConcurrentDictionary)
  3. 我有一个方法,使用一些键创建MyData的新实例
  4. 当我需要获取某个密钥的MyData时,我会检查它是否存在于我的存储中,然后从集合中使用它,否则会创建新实例并将其放入集合中
  5. 我有一些事件,当我应该使缓存无效。在这个事件中,我清空存储

问题是MyData是一次性的。我不知道什么时候应该调用Dispose方法。在清除缓存事件上清除集合时,我无法调用Dispose方法,因为某些线程可以立即使用MyData的此实例。

我应该选择什么图案?

在这种情况下,当缓存的消费者应该能够用缓存中的项完成当前操作时,我看不出并发收集有多大意义。您确实需要在此处进行同步。

最明显的是,您可以在这里使用ReaderWriteLockSlim和常规Dictionary<TKey, TValue>的包装器。

当有人想使用缓存中的项时,它会获得读取访问权限。当有人想要修改缓存(添加项目或使缓存失效)时,它会获得写访问权限(因此,写入程序不能使缓存失效,直到最后一个读卡器不会释放锁)。

另一种选择是考虑方法,当您刚刚捕获ObjectDisposedException时。但这种方法假设电流操作可以从外部中断。

我认为应该封装缓存机制,没有人应该调用dispose。封装字典的对象应该在没有外部干预的情况下完成(Singleton模式在这里会很好,所有对字典的访问都应该被锁定,如果缓存无效,只需再次锁定它即可处理它并清除它。如果你需要Singleton的帮助,请告诉我。

如果对象在逻辑上是不可变的,创建起来有点昂贵,并且已知不消耗不可替代的资源,只消耗少量的可替代资源;如果跟踪对它们的所有引用是不切实际的,您可以考虑使用短弱引用的缓存。这种情况是我认为"依赖"终结是合理的少数情况之一,因为在任何给定时间,只有一个与给定键匹配的对象会存在于"可刷新"队列(需要清理的对象列表)之外。这种方法的一个优点是,如果您避免重新启动符合最终确定条件的对象,那么在大多数情况下,您的代码不必太担心线程问题。你必须定期清理那些关联的弱引用已经失效的条目,并注意缓存条目在被识别为失效后可能会被新对象更新的可能性,但GC应该确保在任何人使用它们时不会清理对象。

最新更新