I'm trying to implement a thread safe, two dimensional collection to control access to multiple resources. The problem is from what I can see I need to perform locking at both the collection level (which is simple enough) and at the individual object level, but not necessarily both at the same time which could potentially cause some problems.
public class LockStore
{
private object _syncLock = new object();
private Dictionary<string, StoredLock> _locks = new Dictionary<string, StoredLock>();
public StoredLock GetOrAdd(string id, StoredLock lockDetails)
{
if (!_locks.ContainsKey(id))
lock (_syncLock)
{
if (!_locks.ContainsKey(id))
_locks.Add(id, lockDetails);
}
return _locks[id];
}
public void Remove(string id)
{
lock (_syncLock)
{
_locks.Remove(id);
}
}
}
public class StoredLock
{
public string Id { get; set; }
public DateTime CreatedDateTime { get; set; }
}
Say for example, a thread could call into the LockStore.GetOrAdd() method, returning a StoredLock object. I'd then like to lock the StoreLock object to prevent other threads from being able to access it, but without holding the lock for the entire dictionary.
var id = "someId"
var storedLock = lockStore.GetOrAdd(id, new StoredLock());
lock (storedLock)
{
//Do something
}
And at some point in a different thread entirely...
lockStore.Remove(id);
At the point the lock is acquired on the StoredLock object stored within the LockStore, the lock is not held for the LockStore so theoretically LockStore.Remove() could be invoked for that particular Id as the Remove() method has no understanding of the locks held on the objects it actually contains. I'm not sure what would happen in this circumstance but I don't think it would be good!
Also, I think this could potentially violate the design principle that objects used for locking aren't publicly accessible?
I'm really at a loss with this, so any suggestions re: solving the problem or the actual approach would be very much appreciated.
EDIT: to be particularly specific - I do not want to hold the lock on the LockStore collection and the individual StoredLock at the same time as this would slow down the processing considerably.