我应该使用Application.Lock()吗?

时间:2010-09-03 13:42:37

标签: asp.net multithreading

请考虑以下情况:我在ASP.NET中使用Application对象来存储多个用户同时访问的集合(List(of MyObject))。虽然我理解从Application对象读取是线程安全的,但我想知道如何使这段代码线程安全:

objList = Application("GlobalList")

objList.add(AnotherValue)

application("GlobalList") = objList

objList = Application("GlobalList")

dim PrunedList as MyObject() = (from o as MyObject in objList where o.SomeProperty = SomeValue).ToArray()

objList.Clear()

For each PrunedListObject as MyObject in PrunedList
   objList.add(PrunedListObject)
next

application("GlobalList") = objList

我读了一些关于Application.Lock()的内容,它基本上是一个互斥体,但我担心在操作Application("GlobalList") 是否正确的方法时阻塞其他线程的性能影响?

1 个答案:

答案 0 :(得分:2)

我不是专门的ASP.NET专家,但我确实使用了几年。几乎所有的应用程序存储都存在与传统ASP的向后兼容性。你需要try / finally块来锁定和解锁,它仍然不像使用.NET中其他传统ASP中没有的其他锁定机制一样灵活。

在您的示例中,锁定/解锁需要非常广泛,因为即使您已经抓住“GlobalList”,同时写入此集合的多个线程仍会导致并发问题。

但一般来说,对集合的任何多线程读/写访问本质上都是不安全的。任何集合都会遇到同样的问题。但是使用静态字段,您可以让多个线程以强类型方式访问单个值,而不需要字典所需的“魔术字符串”。在许多情况下你也不需要锁定。

您可以在不使用应用程序存储的情况下执行此类操作。请注意,您仍然需要同步对集合的访问权限,但不需要锁定/解锁整个应用程序状态字典。

Private Shared GlobalList As New List(Of Foo)()

...

SyncLock GlobalList
    // Only one thread can proceed here at a time
End SyncLock

如果由于多个阅读器相互阻塞而性能确实受到影响,即使没有写入,您也可以切换到使用读写器锁定。在.NET中有一个名为ReaderWriterLockSlim的实现,它允许多个读者同时执行,只要没有编写者持有锁。当读者多于作者时,这可以显着提高性能。使用这种锁有点棘手,因为没有像C#的锁语句或VB的SyncLock那样的语法糖。

修改

如下面的评论所述,您应该始终考虑使用的任何锁定策略的性能影响。特别是,如果读者之间没有很多争用,ReaderWriterLockSlim实际上可能会降低性能。这是MSDN上比较Monitor和ReaderWriterLockSlim的帖子。 http://blogs.msdn.com/b/pedram/archive/2007/10/07/a-performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx