Should I be using Application.Lock()?
Consider the following situation: I'm using the Application
object in ASP.NET to store a collection(List(of MyObject)
) that is being accessed concurrently by several users. While I understand that reading from the Application object is thread safe, I'm wonder how I开发者_StackOverflow should make this code thread safe:
objList = Application("GlobalList")
objList.add(AnotherValue)
application("GlobalList") = objList
or
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
I read a little about Application.Lock() which basically is a mutex but I worry about the performance impact blocking other threads while manipulating Application("GlobalList")
Is Application.Lock() the correct approach?
I'm not an expert in ASP.NET specifically, but I did use it for a few years. Pretty much the Application storage is there for some sense of backwards compatibility with classic ASP. You would need try/finally blocks to lock and unlock and it's still not nearly as flexible as using some of the other locking mechanisms in .NET that were not there in classic ASP.
In your example, Lock/Unlock would need to be very broad because even after you've grabbed "GlobalList" multiple threads writing to this collection at the same time will still cause concurrency problems.
But in general, any multi-threaded read/write access to a collection is inherently unsafe. You would have the same problem with any collection. But using static fields, you could have multiple threads accessing individual values in a strongly typed fashion with no "magic strings" as is required by a dictionary. Also you wouldn't need to lock in many cases.
You could do something like this without using the Application storage at all. Note that you still need to synchronize access to the collection but you don't need to lock/unlock the entire application state dictionary.
Private Shared GlobalList As New List(Of Foo)()
...
SyncLock GlobalList
// Only one thread can proceed here at a time
End SyncLock
If performance does become impacted due to multiple readers blocking each other even if no writes are going on, you can switch to using a reader-writer lock. There is an implementation of this in .NET called ReaderWriterLockSlim that allows multiple readers to execute concurrently as long as there are no writers holding the lock. This gives you significantly better performance when there are more readers than writers. Using this kind of lock is a bit trickier though because there is no syntactic sugar like C#'s lock statement or VB's SyncLock.
EDIT
As noted in the comments below, you should always consider the performance implications of whatever locking strategy you use. In particular, ReaderWriterLockSlim may actually degrade performance if there is not a lot of contention between readers. Here's a post on MSDN comparing Monitor and ReaderWriterLockSlim. http://blogs.msdn.com/b/pedram/archive/2007/10/07/a-performance-comparison-of-readerwriterlockslim-with-readerwriterlock.aspx
精彩评论