应用程序与缓存:锁机制

6

在Asp.net中,Application类具有Lock机制以支持线程安全。

我们知道-Application可以全局访问。

示例:

Application.Lock();
Application["MyCode"] = 21;
Application.UnLock();

好的。

但是

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

那么为什么Application有锁机制而Cache没有?

1个回答

6

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

另一方面,新的 Cache 对象是随着 ASP.NET 引入的,它允许您使用自己的锁定语义。您可以使用 .NET 的 lock 语句来确保线程安全地访问 Cache 对象,同时使您的 Web 应用程序尽可能并行。 lock 语句更安全,因为在退出 lock 块时,锁定将被释放,而 Application 对象不能保证这一点。Cache 还提供了自动过期机制,这更适合用作缓存。它还可以根据依赖关系和可选优先级来过期键,当然,Application 对象缺乏这些功能。

我认为没有理由使用 Application 而不是 Cache 对象。

例如:假设您的缓存中有一百个项目,并且您想要将单个项目存储在缓存中(如果它还不存在)。当您使用 Application 时,您需要执行以下操作:

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

在这种情况下,即使访问与应用程序对象完全无关,所有对应用程序对象的访问也会被阻止。并且如果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();
        }
    }
}

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


1
Microsoft已经使Cache集合线程安全。不需要外部锁定。 - Chris Gessler
3
缓存本身是线程安全的,但仅保证原子性而非一致性。请看上面的示例代码。如果没有lock语句,多个线程将同时调用getValue()无论缓存是否线程安全。 - Sedat Kapanoglu
我想知道这个回答被踩的原因,理由是“这个回答没有用”?真的吗? - Sedat Kapanoglu
你错了。它只是为了与那些古老的过时编程模型兼容而存在。应用程序本身也是线程安全的。http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.aspx 而它被称为“线程安全”并不意味着你不能像我之前说过的那样破坏它的一致性。 - Sedat Kapanoglu
如果您所说的“一致性”是指同步访问,那么我同意。我猜Lock()和Unlock()方法只存在于遗留代码中,现在并不真正需要它们了。 - Chris Gessler
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接