多线程删除HttpRuntime.Cache项目到期

问题描述:

即使我使用锁与静态锁定对象来锁定我的代码同时访问同一项目,我怎样才能保证这个项目不被HttpRuntime从另一个线程中删除在我的锁?我在HttpRuntime或HttpRuntime.Cache中看不到任何SyncRoot属性。多线程删除HttpRuntime.Cache项目到期

如果我指定过期回调并锁定该回调中的静态锁定器对象,是否适合这样做?

在回调中锁定HttpRuntime.Cache过期线程是不是很糟糕?

寻找“SyncRoot”属性建议您在将锁与集合结合使用时使用SyncRoot属性。有一个原因,尽管后面的集合为后向兼容提供了支持,但通过显式实现接口,它往往会隐藏起来。真的,SyncRoot的想法不是很好。

在这种情况下,您正在讨论一个线程安全的集合,所以更少需要。 System.Web.Caching.Cache自己执行锁定(或其他机制,它被指定为线程安全的,而不是通过特定方法进行线程安全),因此通过多个线程添加,访问和从集合中删除项目不会破坏它。

剩下的唯一风险是,如果对象本身不是线程安全的,或者如果您从同一个线程中多次访问集合。

第二个很容易避免不这样做。如果你这样做:

(HttpRuntime.Cache.Get(someKey) as SomeType).SomeMethod(); 
(HttpRuntime.Cache.Get(someKey) as SomeType).SomeOtherMethod(); 

这才有意义,如果你想可能会被处理在比第一第二呼叫不同的对象。否则,它是很容易解决的。

SomeType obj = HttpRuntime.Cache.Get(someKey) as SomeType; 
obj.SomeMethod(); 
obj.SomeOtherMethod(); 

(你也不能重复调用Get方法获得稍许的性能提升

如果你需要担心不同的线程调用SomeMethod()SomeOtherMethod()在同一时间你需要确保这些方法是线程安全的,或者锁定与所讨论对象相关的对象。大多数情况下,与对象相关的对象最明显的选择是该对象本身。因此:

SomeType obj = HttpRuntime.Cache.Get(someKey) as SomeType; 
lock(obj) 
{ 
    obj.SomeMethod(); 
    obj.SomeOtherMethod(); 
} 

(请注意,即使SomeMethod()SomeOtherMethod()是线程安全的,如果它们的组合不是线程安全的,我们仍然可能需要执行此操作。例如。如果第一个报道的对象状态,我们决定在此基础上是否要进行第二次,那么我们通常需要围绕锁定,防止国家的第一和第二个方法调用)之间变化。

当然,对象上的所有其他操作都需要以相同的方式锁定。如果我们有多个对象需要同步作为一个单元,它会变得更加复杂。然后,我们需要一个更复杂的规则,关于我们锁定的对象,只需锁定所讨论的对象;因为没有单一的“有问题的对象”。

+0

有趣的观察 - 我也从来不必在集合上使用SyncRoot。原因是我不期望除了我的代码以外的任何东西来修改这些集合,所以我使用自己的对象或集合对象在需要时进行锁定。在这种情况下,框架随时更新它,可能与我处理请求的时间相同 - 因此我担心。 – alpav 2012-08-14 15:32:09

+0

@alpav的想法是,不同的代码 - 集合的内部和外部 - 可以同意如何锁定它。不幸的是,如果没有一种机制来适应更广泛的锁定(例如同时锁定两个不同的集合),它实际上并不奏效。 – 2012-08-14 15:48:59

缓存是您的应用程序的私有缓存。运行时只对应用程序重新启动(即清除缓存)时执行任何操作。当您将一个项目添加到缓存中时,如果您确实没有其他任何东西与缓存混淆,则可以提供回调以通知删除。

我认为最好是设计应用程序和缓存中的内容,以尽量减少缓存中两个事物访问同一项目的需求。需要两个线程访问缓存中的相同项目表明存在设计问题。

+0

我的缓存的目的是为了节省对于具有相同的签名,这因此意味着不同的线程将有可能尝试访问和创建如果不存在相同的缓存项不同的查询(从多个线程来)被重用的数据。我的目的(设计)有什么问题? – alpav 2012-08-22 18:46:36