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

时间:2013-12-16 08:54:50

标签: c# multithreading caching idisposable

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

  1. 我有一些数据类,我要缓存,ex MyData
  2. 我正在为MyData
  3. 创建一些集合(例如ConcurrentDictionary)
  4. 我有使用某个键创建MyData新实例的方法。
  5. 当我需要获取某些密钥的MyData时,我会检查它是否存在于我的存储中 - 然后从集合中使用它,否则创建新实例并将其放入集合中
  6. 我有一些事件,当我应该使缓存无效。在这个事件上,我清除存储。
  7. Probles是MyData是Disposable。我不知道何时应该调用Dispose方法。在clear-cache事件清除集合时我无法调用Dispose方法,因为有些线程可以在一瞬间使用MyData的这个实例。

    我应该选择什么模式?

3 个答案:

答案 0 :(得分:2)

在这种情况下,当缓存的使用者应该能够使用缓存中的项目完成当前操作时,我看不出有很多意义。你真的需要在这里进行同步。

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

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

另一种选择是在您捕捉ObjectDisposedException时考虑方法。但是这种方法假定当前的操作可以从外部中断。

答案 1 :(得分:1)

我认为你应该封装缓存机制,没有人应该调用dispose包装字典的对象应该这样做而不需要外部干预(Singleton模式在这里会很好,所有对字典的访问都应该被锁定,在你使缓存无效的事件只需将其锁定再次处理它并清除它。如果你需要单身人士的帮助告诉我。

答案 2 :(得分:1)

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