我有一个帮助器类,它读取一个大的XML文档并生成一个c#对象列表。
我经常使用这些对象,所以我认为最好的方法是将它们保存在内存中,然后从内存中访问它们。
我创建了一个简单的存储库,它从内存中获取一个对象,如果不存在,就添加它。
存储库如下所示:
public class XmlDocumentRepository
{
private readonly ICacheStorage _cacheStorage;
public XmlDocumentRepository(ICacheStorage cacheStorage)
{
_cacheStorage = cacheStorage;
}
private readonly object _locker = new object();
private void DeserializeXmlDocument()
{
lock (_locker)
{
// I deserialize the xml document, i generate the c# classes, and save them in cache
IEnumerable<Page> pages = new XmlDeserializerHelper().DeserializeXml();
foreach(var page in pages)
{
_cacheStorage.Add(page_Id, page);
}
}
}
public Page GetPage(Guid page_Id)
{
Page page = _cacheStorage.Get<Page>(page_Id);
if (page != null)
return page;
lock (_locker)
{
page = _cacheStorage.Get<Page>(page_Id);
if (page != null)
return page;
DeserializeXmlDocument();
page = _cacheStorage.Get<Page>(page_Id);
return page;
}
}
}XmlDocumentRepository在web应用程序内部使用(更准确地说是asp.net mvc )。
存储库的实现好吗?我是否正确地使用了lock语句?
发布于 2013-03-06 21:02:09
在我对这个问题的评论中,我误解了共享的缓存。我认为您需要执行以下选项之一:
XmlDocumentRepository实例之间共享它。发布于 2013-03-06 20:38:58
作为主要规则,您希望保护对由多个线程使用的数据存储的所有访问变体。我在你的实现中看到了几个潜在的问题;
1: ICacheStorage是从外部提供的,这意味着这个集合可以在其他地方修改,这可能会受到锁的保护,也可能不会。也许您应该要求集合本身使用内部锁定,或者其他类型的线程安全机制?
2:数据访问锁保护不一致。在GetPage中,您在应用锁之前访问_cacheStorage,而在反序列化中,您在锁中访问它。这意味着您可能会得到一个结果,其中一个正在添加到缓存中,而另一个正在从缓存中获取。
3:对于缓存、xml读取,还是两者都要求线程安全?如果只需要保护缓存,那么可以将xml的读取移到锁之外。如果同时保护这两个函数,则应该将整个GetPage函数放入锁中。
https://stackoverflow.com/questions/15247068
复制相似问题