安全地使用’HttpContext.Current.Cache’

我在这样的Web服务方法中使用Cache

 var pblDataList = (List)HttpContext.Current.Cache.Get("pblDataList"); if (pblDataList == null) { var PBLData = dc.ExecuteQuery(@"SELECT blabla"); pblDataList = PBLData.ToList(); HttpContext.Current.Cache.Add("pblDataList", pblDataList, null, DateTime.Now.Add(new TimeSpan(0, 0, 15)), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); } 

但我想知道,这段代码是否是线程安全的? Web服务方法由多个请求者调用。 当缓存为空时,多个请求者可能会尝试检索数据并同时添加到Cache中。

查询需要5到8秒。 是否会围绕此代码引入锁定语句以防止任何可能的冲突? (我知道多个查询可以同时运行,但我想确保一次只运行一个查询。)

缓存对象是线程安全的, 但后台线程无法使用HttpContext.Current 这可能适用于您,也可能不适用于您,从您的代码段开始,您是否实际使用后台线程并不明显,但如果您现在或将来某个时候决定,您应该记住这一点。

如果您有可能需要从后台线程访问缓存,请改用HttpRuntime.Cache 。

此外,虽然缓存上的单个操作是线程安全的,但顺序查找/存储操作显然不是primefaces操作。 您是否需要它们是primefaces的取决于您的特定应用。 如果同一个查询运行多次可能是一个严重的问题,即它是否会产生比数据库能够处理的更多负载,或者如果请求返回的数据立即被覆盖,则会出现问题缓存,那么你可能想要锁定整个代码块。

但是,在大多数情况下,您真的想首先分析并查看这是否真的是一个问题。 大多数Web应用程序/服务都不关心缓存的这一方面,因为它们是无状态的,并且缓存是否被覆盖并不重要。

你是对的。 检索和添加操作不会被视为primefaces事务。 如果您需要阻止查询多次运行,则需要使用锁定。

(通常情况下这不是什么大问题,但是对于长时间运行的查询,可以减轻数据库的压力。)

我相信Add应该是线程安全的 – 即如果使用相同的键调用Add两次,它将不会出错,但显然查询可能会执行两次。

然而,另一个问题是数据线程安全 。 无法保证每个List都是隔离的 – 它取决于缓存提供者。 内存缓存提供程序直接存储对象,因此如果任何线程编辑数据(在列表中添加/删除/交换项目,或更改其中一个项目的属性),则存在冲突风险。 但是,对于序列化提供程序,您应该没问题。 当然,这要求blabla可序列化……