【发布时间】:2009-12-18 18:04:38
【问题描述】:
对不起,我有很多关于锁/缓存的问题。=_=..
->1。关于缓存,我知道asp.net中的缓存是线程安全的,我常用的简单代码是
IList<User> user= HttpRuntime.Cache["myCacheItem"] as IList<User>;
if (user == null)
{
//should i have a lock here?
//lock(some_static_var){...}
HttpRuntime.Cache["myCacheItem"] = GetDateFromDateBase();
}
return user;
应该在代码中使用锁吗?
->->1.1 如果我使用,也许我应该声明许多锁定项?我在社区服务器中看到了一些实现,它使用静态字典来存储 lockitem,这是个好主意吗?因为我担心字典中的锁定项可能太多,可能会减慢系统速度。
->->1.2 如果我不使用,会发生什么?可能只有两个或更多线程访问GetDateFromDateBase()?如果只是这样,我想也许我可以放弃锁定。
->2.我有一个通用字典存储在缓存中,我必须修改(添加/更新/删除)它。我只是用它来获取像 dic.trygetvalue(key) 这样的值,不要循环它。
->->2.1 如果我能保证修改只发生在一个线程中,那么场景就像
a.aspx -> 从缓存中读取字典,并显示在页面上,对用户公开
b.ashx -> 调用时会修改字典。(循环5分钟),私有使用
我应该在 a/b 中使用锁定吗?锁定读写器?
->->->2.11 如果我不使用任何锁,会发生什么?读写器同时访问会抛出异常吗?
->->->2.12 如果我只是将编写器锁定在 b.ashx 中,会发生什么? a.aspx 中的阅读器会被屏蔽吗?处理这种情况的最佳做法是什么?
->->2.2 如果读写器都发生在多线程访问中。它们都是公开页面。
a.aspx -> 只是从缓存中读取
b.aspx -> 修改字典
怎么办?全部锁定?
->->2.3 如果我实现一个新的字典添加功能:
它只是将当前字典复制到新字典,然后添加新项目或修改
最后返回新的dic,它会解决并发问题吗?
哈希表会解决这些问题吗?
如何确定一个项目需要被锁定?我认为我在这些事情上错了=_=。
->3.最后一个问题..我有两个网络应用程序
a -> 显示网络
b -> 管理一些设置
他们都有自己的缓存,我可以并发两个缓存吗?
[2.1] 中的操作是否正确或其他操作?(我测试了 memcached 但它比 web 应用程序中的速度太慢,所以我只使用了两个)
感谢您阅读所有内容-_-...
希望你能知道我在说什么:)
更新======================================== ===============
感谢亚伦的回答。看完他的回答后,我试着回答自己:)
1.关于缓存,如果数据不会被修改,可以先在Application_Start(global.asax)中读入缓存。
1.1 如果锁,我应该在读取数据时添加锁开始,而不仅仅是写入。锁定项目应该是静态的,但我也对 1.1 感到不确定。
1.2 是的,如果您可以假设代码只是从数据库中读取日期然后插入缓存并且不会修改(对吗?-_-)。这个结果可能会从数据库中读取多次。我认为这不是一个大问题。
2. 泛型字典写入不是线程安全的,所以修改时要加锁。为了解决这个问题,我可以使用不可变字典。
但是如果我在.net4.0 中使用ConcurrentDictionary(读/写时线程安全)或者我自己实现一个新字典(使用读写器锁),它会解决吗?修改时需要重新锁定吗?代码就像
ConcurrentDictionary user= HttpRuntime.Cache["myCacheItem"] as ConcurrentDictionary;
if (user == null)
{
//is it safe when the user is ConcurrentDictionary?
HttpRuntime.Cache["myCacheItem"] = GetDateFromDateBase();
}
else
{
//is it safe when the user is ConcurrentDictionary?
user["1"] = a_new_user;
}
3.问题是,我有一个像stroe这样的小应用程序,它有两个Web应用程序一个是商店展示站点(A),另一个是管理站点(B),所以我需要并发两个Web缓存,像这样,如果我在 B 中修改产品价格,我如何通知站点 A 更改/删除缓存?(我知道 A 中的缓存可以设置 shortor,但不会很快,所以我想知道是否有内部支持 asp.net 还是像问题 2.1 一样?有一个 aspx/ashx 页面可以调用吗?)
【问题讨论】:
-
是的,您需要同时锁定读取和写入。如果您使用
ConcurrentDictionary,那么您不需要锁,但请确保在适用的情况下使用AddOrUpdate/GetOrAdd方法。但是缓存项本身仍然存在竞争条件,这就是为什么我建议在Application_Start中对其进行初始化,因此您永远不必检查是否为空。至于您的缓存“共享”要求,如果数据库正在更新,您可以使用SqlCacheDependency,否则您实际上是在谈论 IPC,我建议您开始一个新问题(或者更好的是,搜索现有问题) .
标签: asp.net caching dictionary thread-safety locking