应用程序与缓存:锁定机制

Roy*_*mir 6 c# asp.net caching .net-4.0

Applicationasp.net中的类具有Lock支持线程安全的机制.

我们知道 - Application可以在全球范围内访问.

样品:

Application.Lock();
Application["MyCode"] = 21;
Application.UnLock();
Run Code Online (Sandbox Code Playgroud)

好.

也是Cache全局可访问的(并没有锁机制,也用于删除/添加项目)

那为什么Application有一个锁定机制而Cache不是?

Sed*_*glu 6

Application是旧ASP技术的数据存储.它有一个全局锁.当您调用Application.Lock()对所有线程中的Application对象的所有访问都被阻止时.

另一方面Cache,ASP.NET引入的新对象允许您使用自己的锁定语义.您可以使用.NET的lock语句来确保对Cache对象的线程安全访问,同时使Web应用程序尽可能保持并行.该lock语句更安全,因为当您退出lock块时保证锁定被释放.应用程序对象不保证.缓存还提供自动过期机制,更适合缓存.它还可以基于依赖性契约和可选优先级使密钥到期,这当然是Application对象所缺乏的.

我认为没有理由使用ApplicationCache的对象.

示例:假设您在缓存中有100个项目,并且如果某个项目尚未存在,则您要将其存储在缓存中.使用时Application,执行以下操作:

if(Application["someData"] == null) 
{
    Application.Lock();
    if(Application["someData"] == null) 
    {
        Application["someData"] = getValue(); //a very long time consuming function
    }
    Application.Unlock();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,即使它们完全不相关,也会阻止对Application对象的所有访问.如果getValue()导致异常导致应用程序挂起,因为锁定未释放.你需要包裹一个try...... finally以确保它是安全的.

另一方面,当使用Cache对象时,您执行此操作:

if(Cache["someData"] == null)
{
    lock(myLockObject)  // or other shared lock for that single value
    {
        if(Cache["someData"] == null)
        {
            Cache["someData"] = getValue();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,只有需要访问的代码块myLockObject才会等待.访问的其他人Cache将并行运行就好了.如果getValue()抛出异常,则释放锁定而不会出现任何问题,让其他线程继续执行.

  • 缓存本身是线程安全的,只能保证原子性而不是一致性.看看上面的示例代码.如果你没有`lock`语句,那么多个线程将同时调用`getValue()`,无论缓存是否是线程安全的. (3认同)