在ASP.NET中运行时创建动态锁

以下假设对此代码有效吗? 我在代码下面加了一些背景信息,但我认为它不相关。

假设1:由于这是一个单一的应用程序,我假设它将由一个进程处理。 因此,静态变量在线程之间共享,并且静态地声明我的锁对象集合是有效的。

假设2:如果我知道该值已经在字典中,我不需要锁定读取。 我可以使用ConcurrentDictionary,但我相信这个是安全的,因为我没有枚举(或删除),并且当我调用UnlockOnValue()时,该值将存在而不会改变。

假设3:我可以锁定Keys集合,因为即使底层数据结构存在,该引用也不会改变。

 private static Dictionary LockList = new Dictionary(); 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块。 如果抛出exception,它将永远不会释放其锁定。

2:LockOnValue效率有点低,因为它会进行两次字典查找。 对于小字典而言,这不是什么大问题,但对于较大的字典,您将需要切换到TryGetValue。

此外,你的假设3成立 – 至少目前如此。 但是Dictionary合约不保证Keys属性总是返回相同的对象。 而且由于不容易依赖于此,我建议不要这样做。 每当我需要一个对象锁定时,我只是为了这个目的而创建一个对象。 就像是:

 private static Object _lock = new Object(); 

lock只具有单个进程的范围。 如果要跨越进程,则必须使用Mutex (已命名)等原语。

lockMonitor.EnterMonitor.Exit相同。 如果你也做Monitor.EnterMonitor.Exit ,它就是多余的。

您不需要锁定读取,但是您必须锁定检查该值是否存在并添加它的“事务”。 如果您没有锁定该系列指令,则在检查密钥和添加密钥并添加密钥时可能会出现其他情况 – 从而导致exception。 您正在执行的锁定就足够了(您不需要对Enter和Exit进行额外调用 – 锁定会为您执行此操作)。