【问题标题】:Multithreaded removal of HttpRuntime.Cache items upon expiration过期时多线程删除 HttpRuntime.Cache 项
【发布时间】:2012-08-08 05:36:19
【问题描述】:

即使我使用 lock 和静态 locker 对象来锁定我的代码同时访问同一个项目,我如何保证在我的锁定期间 HttpRuntime 不会从另一个线程中删除该项目?我在 HttpRuntime 或 HttpRuntime.Cache 中看不到任何 SyncRoot 属性。

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

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

【问题讨论】:

    标签: asp.net multithreading caching iis-7.5 httpruntime.cache


    【解决方案1】:

    缓存是您的应用程序的私有缓存。运行时唯一对其进行任何操作的时间是应用程序重新启动时(即它清除缓存)。当您将项目添加到缓存中时,如果您真的想确保没有其他东西会干扰您的缓存,则可以提供回调以通知删除。

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

    【讨论】:

    • 我的缓存的目的是保存数据以供具有相同签名的不同查询(来自多个线程)重用,这意味着如果不存在不同的线程可能会尝试访问和创建相同的缓存项。我的目的(设计)有什么问题?
    【解决方案2】:

    寻找“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() 是线程安全的,如果它们的组合不是线程安全的,我们可能仍然需要这样做。例如,如果第一个报告对象状态并且我们决定根据是否执行第二个,那么我们通常需要锁定它以防止第一个和第二个方法调用之间的状态发生变化。

    当然,对象上的所有其他操作都需要以相同的方式锁定。如果我们需要将多个对象作为一个单元进行同步,它会变得更加复杂。然后我们需要一个更复杂的规则,即我们锁定什么对象,而不是简单地锁定有问题的对象;因为没有单一的“有问题的对象”。

    【讨论】:

    • 有趣的观察 - 我也从未在集合上使用过 SyncRoot。原因是除了我的代码之外我不期望任何东西来修改这些集合,所以我在需要时使用我自己的对象或集合对象来锁定。在这种情况下,框架会随时更新它,可能在我处理请求的同时 - 因此我担心。
    • @alpav 的想法是,集合内部和外部的不同代码可以就如何锁定它达成一致。不幸的是,如果没有一种机制来说明如何将其融入任何更广泛的锁定(例如同时锁定两个不同的集合),它就无法真正起作用。
    猜你喜欢
    • 2011-09-28
    • 2017-09-01
    • 1970-01-01
    • 2011-05-07
    • 2012-07-22
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多