如果我修改字典时不锁定它会发生什么?关于asp.net缓存
对不起,我有很多关于锁/缓存的问题 ->一,。关于缓存,我知道asp.net中的缓存是线程安全的,我通常使用的简单代码是如果我修改字典时不锁定它会发生什么?关于asp.net缓存,asp.net,caching,dictionary,thread-safety,locking,Asp.net,Caching,Dictionary,Thread Safety,Locking,对不起,我有很多关于锁/缓存的问题 ->一,。关于缓存,我知道asp.net中的缓存是线程安全的,我通常使用的简单代码是 IList<User> user= HttpRuntime.Cache["myCacheItem"] as IList<User>; if (user == null) { //should i have a lock here? //lock(some_static_var){...}
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;
3.问题是,我有一个像stroe这样的小应用程序,它有两个web应用程序,一个是商店展示站点(a),另一个是管理站点(B),所以我需要同时使用两个web缓存,比如如果我在B中修改产品价格,我如何通知站点a更改/删除缓存?(我知道A中的缓存可以设置为shortor,但不会很快,所以我想知道asp.net中是否有内部支持,或者像问题2.1一样?是否有一个aspx/ashx页面可以调用?)
线程安全意味着您不必担心多个线程同时读写同一个缓存项。简单的读写操作不需要任何类型的锁 但是,如果您试图执行应为原子操作的操作,例如,检查项目是否存在,如果不存在则添加该项目,则需要同步或序列化访问。因为锁需要是全局的,所以通常最好在
中声明一个静态只读对象
e> global.asax
并在执行原子操作之前锁定。请注意,您应该在读取之前锁定,并且只在写入之后释放锁定,因此您在上面示例中假设的锁定实际上发生得太晚了
这就是为什么许多web应用程序不延迟加载缓存;相反,它们在应用程序启动
方法中执行加载。至少,在缓存中放入一个空字典可以省去检查null
的麻烦,这样您就不必进行同步,因为您只需要访问空字典他缓存项目一次(但继续阅读)
问题的另一个方面是,即使缓存本身是线程安全的,它也不会使您添加到缓存中的任何项成为线程安全的。这意味着,如果您在其中存储一个字典,任何检索缓存项的线程都保证获得一个完全初始化的字典,但您仍然可以创建竞争条件和其他原因d-如果您有多个请求试图同时访问字典,并且其中至少有一个请求正在修改字典,则会出现安全问题
NET中的词典可以支持多个并发读取器,但不能支持多个写入器,因此,如果ASP.NET缓存中存储了一个词典,并且有多个线程/请求进行读取和写入,则肯定会遇到问题。如果可以保证只有一个线程会写入词典,则可以将词典用作n不可变类型-即,复制字典,修改副本,并用副本替换缓存中的原始字典。如果字典很少被修改,那么这确实可以为您省去同步访问的麻烦,因为不会有任何请求尝试从正在修改的同一字典中读取。另一方面,如果字典非常大和/或经常修改,那么在复制所有这些副本时可能会遇到性能问题-唯一可以确保的方法是profile,profile,profile
如果您发现性能限制不允许使用该方法,那么唯一的其他选项是同步访问。如果您知道一次只有一个线程会修改字典,则需要读写器锁(即,readerwriterlocksim
)如果你不能保证这一点,那么你需要一个监视器
(或者只是围绕每个操作序列的一个简单的锁(…)
子句)
这应该可以回答问题1-2;很抱歉,我不太明白您在#3中提出的问题。ASP.NET应用程序都是在各自的AppDomain中实例化的,因此实际上不存在任何并发问题,因为没有共享任何内容(除非您实际使用某种IPC方法,在这种情况下,一切都是公平的)
我是否正确理解了您的问题?这有帮助吗?线程安全意味着您不必担心多个线程同时读写同一个缓存项。简单的读写操作不需要任何类型的锁 但是,如果您试图执行应为原子操作的操作,例如,检查项目是否存在,如果不存在则添加该项目,则需要同步或序列化访问。因为锁需要是全局的,所以通常最好在
中声明一个静态只读对象
e> global.asax
并在执行原子操作之前锁定。请注意,您应该在读取之前锁定,并且只在写入之后释放锁定,因此您在上面示例中假设的锁定实际上发生得太晚了
这就是为什么许多web应用程序不延迟加载缓存;相反,它们在应用程序启动
方法中执行加载。至少,在缓存中放入一个空字典可以省去检查null
的麻烦,这样您就不必进行同步,因为您只需要访问空字典他缓存项目一次(但继续阅读)
问题的另一个方面是,即使缓存本身是线程安全的,它也不会使您添加到缓存中的任何项成为线程安全的。这意味着,如果您在其中存储一个字典,任何检索缓存项的线程都保证获得一个完全初始化的字典,但您仍然可以创建竞争条件和其他原因d-如果您有多个请求试图同时访问字典,并且其中至少有一个请求正在修改字典,则会出现安全问题
NET中的词典可以支持多个并发读卡器,但不支持
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;
}