2010-09-03 115 views
2

请考虑以下情况:我在ASP.NET中使用Application对象来存储由多个用户同时访问的集合(List(of MyObject))。而据我所知,从Application对象阅读是线程安全的,我不知道我应该如何使此代码线程安全的:我应该使用Application.Lock()吗?

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")是Application.Lock()的正确方法?

回答

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

+1

虽然我一般同意Josh的回答,但在读/写方案中锁被锁定了很短的时间,'lock'语句仍然胜过'ReaderWriterLockSlim'(即使没有写入) 。当锁内的时间足够大时(根据http://tinyurl.com/rwlsperformance,调用大约100个不可插入的空方法),'ReaderWriterLockSlim'将会很有用。不仅可以让用户更快地“锁定”你的代码,更重要的是,它可以让你更容易理解。 – Steven 2010-09-03 14:32:51

+1

@Steven:我同意。我的个人测试表明,当关键部分能够以快速和快捷的方式执行时,“ReadWriterLockSlim”比普通的旧'lock'慢大约5倍。添加和删​​除“List”中的项目几乎肯定会很快捷。否则,这通常是一个很好的答案。 – 2010-09-03 16:24:17

+1

嗨,大家好,感谢您对ReaderWriterLockSlim的反馈。我知道旧的执行方式只是一条狗,但我认为他们已经更接近于Monitor在新的实施方面的表现。无论如何,除非性能测试另有说明,否则我总是会采用最简单的机制。 – Josh 2010-09-03 17:11:24