Locking individual elements in a static collection?
I have a static collection of objects that will be frequently updated from multiple threads. Is it possible to lock individual ob开发者_JAVA百科jects in a collection instead of locking the entire collection so that only threads trying to access the same object in the collection would get blocked instead of every thread?
If there is a better way to update objects in a collection from multiple threads, I'm all ears.
Refer Data Structures for Parallel Programming on MSDN, These are significantly faster than user locking mechanisms.
The collection classes in the System.Collections.Concurrent namespace provide thread-safe add and remove operations that avoid locks wherever possible and use fine-grained locking where locks are necessary.
Unlike collections that were introduced in the .NET Framework versions 1.0 and 2.0, a concurrent collection class does not require user code to take any locks when it accesses items.
First of all, in an ASP.NET application, you're better off using the HttpCache object, rather a simple static collection.
On to your actual question, you can indeed maintain a single lock for every item in your collection (every object has a monitor in .NET, so they are relatively cheap). However, you probably want to do this in tandem with having a lock for the actual collection:
I'll use static here for simplicity, but as I mentioned above, HttpCache might be better:
class CacheItem
{
private readonly object _lock = new object();
public void DoSomething()
{
lock(_lock)
{
// perform some synchronized action on the individual item
}
}
}
// I'd recommend a reader-writer lock for the
// collection so that you can have multiple retrievals
// of items and still lock exclusively for changing the collection
private static ReaderWriterLockSlim itemsLock = new ReaderWriterLockSlim();
private static List<CacheItem> items = new List<CacheItem>();
public static void AddItem(CacheItem item)
{
itemsLock.EnterWriteLock();
try
{
items.Add(item);
}
finally
{
itemsLock.ExitWriteLock();
}
}
pulbic static CacheItem GetItem(int index)
{
itemsLock.EnterReadLock();
try
{
return items[index];
}
finally
{
itemsLock.ExitReadLock();
}
}
First of all, you never lock an object, it's the code that you lock. The lock doesn't protect the data in any way, it only prevents other threads to enter the same code.
An object is used as identifier for a lock, that way you can use the same identifier to lock several methods, or lock the same method using different identifiers.
To make the lock apply to the methods when they handle specific data, you just need an identifier that is unique for that data. If the data is an object, you can simply use the object itself as identifier.
精彩评论