以下假设对此代码有效吗?我在代码下放置了一些背景信息,但我认为这无关紧要。
假设1:由于这是单个应用程序,因此我假设它将由单个进程处理。因此,静态变量在线程之间共享,并且静态声明我的锁对象集合是有效的。
假设2:如果我知道字典中已经存在该值,则无需锁定读取。我可以使用ConcurrentDictionary,但是我相信这是安全的,因为我没有枚举(或删除),并且当我调用UnlockOnValue()
时,该值将存在并且不会更改。
假设3:我可以锁定Keys集合,因为即使基础数据结构发生更改,该引用也不会更改。
private static Dictionary<String,Object> LockList =
new Dictionary<string,object>();
private void LockOnValue(String queryStringValue)
{
lock(LockList.Keys)
{
if(!LockList.Keys.Contains(queryStringValue))
{
LockList.Add(screenName,new Object());
}
System.Threading.Monitor.Enter(LockList[queryStringValue]);
}
}
private void UnlockOnValue(String queryStringValue)
{
System.Threading.Monitor.Exit(LockList[queryStringValue]);
}
然后,我将使用如下代码:
LockOnValue(Request.QueryString["foo"])
//Check cache expiry
//if expired
//Load new values and cache them.
//else
//Load cached values
UnlockOnValue(Request.QueryString["foo"])
背景:我正在ASP.NET中创建一个应用程序,该应用程序基于查询字符串中单个用户定义的变量下载数据。值的数量将非常有限。我需要在指定的时间段内缓存每个值的结果。
方法:我决定使用本地文件来缓存数据,这不是最佳选择,但是我想尝试一下,因为这不是很关键,并且性能也不是大问题。我为每个选项使用了2个文件,其中一个与缓存的到期日期有关,另一个与数据有关。
问题:我不确定执行锁定的最佳方法是什么,并且我不太熟悉.NET中的线程问题(我选择这种方法的原因之一)。根据可用的内容和我阅读的内容,我认为以上内容应能奏效,但我不确定,并希望第二点意见。
最佳答案
您当前的解决方案看起来不错。我将要更改的两件事:
1:UnlockOnValue需要进入finally块。如果抛出异常,它将永远不会释放其锁。
2:LockOnValue效率不高,因为它两次进行了字典查找。对于一本小的字典来说,这并不是什么大问题,但是对于一本更大的字典,您将需要切换到TryGetValue。
另外,您的假设3成立-至少目前是这样。但是Dictionary契约(Contract)不能保证Keys属性始终返回相同的对象。而且因为不依赖它很容易,所以我建议不要这样做。每当我需要锁定某个对象时,我仅出于该唯一目的创建一个对象。就像是:
private static Object _lock = new Object();