即使我使用带有静态锁定器对象的锁来锁定我的代码同时访问同一个项目,我如何保证在锁定期间HttpRuntime不会从另一个线程中删除此项目?我在HttpRuntime或HttpRuntime.Cache中看不到任何SyncRoot属性。
如果我指定过期回调并在该回调中锁定我的静态锁定器对象,那么这样做是否合适?
在回调中锁定HttpRuntime.Cache到期线程是不是很糟糕?
答案 0 :(得分:1)
查找“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()
是线程安全的,如果它们的组合不是线程安全的,我们可能仍然需要这样做。例如,如果第一个报告对象状态我们决定是否执行第二个,然后我们通常需要锁定它以防止状态在第一个和第二个方法调用之间发生变化。)
当然,对象上的所有其他操作都需要以相同的方式锁定。如果我们需要将多个对象作为一个单元进行同步,则会变得更加复杂。然后我们需要一个更复杂的规则,关于我们锁定什么对象,只需锁定有问题的对象;因为没有单一的“有问题的对象”。
答案 1 :(得分:0)
缓存是应用程序的专用缓存。运行时唯一的任务是重启应用程序(即清除缓存)。当您将项目添加到缓存时,如果您确实希望确保没有其他任何内容弄乱您的缓存,则可以提供回调以通知删除。
我认为最好设计应用程序以及缓存中的内容,以便尽可能减少访问缓存中同一项目的两件事。需要两个线程访问缓存中的相同项目表明存在设计问题。