I have custom collection and I want to add wrapper to allow concurrent access.
public class MyConcurrentCollection<T>
{
private MyCollection _collection; // passed in constructor
public void Add(T item)
{
//modifies and may temporarily "break" the collection while executing this method
}
public bool Contains(T item)
{
//only reads
}
// other read and write methods
}
At this moment, I have object
private member that acts as lock in every method, allowing only one thread at a time to access the collection, so every method looks like this:
public bool Contains(T item)
{
lock(_lock)
{
return _collection.Contains(item);
}
}
However this seems really inefficient. Since Contains()
only reads from the collection, should I allow multiple threads into it?
Of course, I need to lock access to Add()
and other methods while there are threads in Contains()
and I need to block access to Contains()
if there is a thread wishing to modify the collection.
Is there any disadvantage of allowing multiple threads into read only methods, or should I stick with my basic solution?
Best Answer
It is inefficient but it is necessary - what happens if you read from the collection while someone else is adding a new entry but, in the way of threading, hasn't quite finished writing the new entry's data?
There are ways to make it more efficient, particularly using a read-write lock, which locks the entire collection to both readers and writers if someone is writing, but allows multiple readers access (ie a read lock prevents a writer - the writer has to wait until you're done reading, but does not block other readers).
Incidentally, using an object as a lock is not considered best practice. Use a dedicated lock construct. I remember reading somewhere the CLR team wish they'd never allowed such use.