Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果我修改字典时不锁定它会发生什么?关于asp.net缓存_Asp.net_Caching_Dictionary_Thread Safety_Locking - Fatal编程技术网

如果我修改字典时不锁定它会发生什么?关于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){...}

对不起,我有很多关于锁/缓存的问题

->一,。关于缓存,我知道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;


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;
}