Search code examples
c#thread-safetyreaderwriterlockslimreaderwriterlock

(C#) make auto GC possible for Dictionary<ReaderWriterLockSlim>


I maintained a dictionary of ReaderWriterLockSlim objects for resource access:(sample code is ugly here, just makes you understand my purpose)

static ConcurrentDictionary<string, ReaderWriterLockSlim> rwResourceLocks =
                                new ConcurrentDictionary<string, ReaderWriterLockSlim>();

And use like this:

if (ResourceStore.Exist("resourceID")) {
    if (rwResourceLocks["resourceID"] == null) {
        /* create a new lock in thread-safe way */
    }
    rwResourceLocks["resourceID"].EnderReadLock();
    var rc = ResourceStore.GetResource("resourceID");
    /* further use of rc... */
    rwResourceLocks["resourceID"].ExitReadLock();    
}

Resources may be added or removed dynamically and their life-cycle is unpredictable (unable to mornitor removal of resource), as amount of resources grows up, size of rwResourceLocks is increasing too which will lead to memory trouble. Is there a way to solve this problem? (Obviously I can't simply call rwResourceLocks.Clear() to do this)

I know it's a bit complicated :(


Solution

  • You could try using a ConditionalWeakTable instead of a ConcurrentDictionary. A ConditionalWeakTable automatically removes a value from the dictionary when its key has been collected by the Garbage Collector.

    ConditionalWeakTable<object, ReaderWriterLockSlim> _locks;
    
    if (ResourceStore.Exists("resourceID")) {
        var rc = ResourceStore.GetResource("resourceID");
        var lck = _locks.GetValue(rc, () => new ReaderWriterLockSlim());
    
        lck.EnterReadLock();
    
        // Use the resource here
    
        lck.ExitReadLock();
    }