2016-03-31 5 views
1

я поддерживал словарь объектов ReaderWriterLockSlim для доступа к ресурсам: (пример кода некрасиво здесь, просто заставляет вас понять свое предназначение)(C#) делают авто GC возможно Dictionary <ReaderWriterLockSlim>

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

И использовать как это:

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();  
} 

ресурсов могут быть добавлены или удалены динамически и их жизненный цикл непредсказуемый (не в состоянии mornitor удаления ресурса), так как объем ресурсов растет, размер rwResourceLocks растет слишком который приведет к памяти беда. Есть ли способ решить эту проблему? (Очевидно, что я не могу просто позвонить rwResourceLocks.Clear(), чтобы сделать это)

Я знаю, что это немного сложнее :(

+0

Существует состояние гонки: если 2 нити проверки же несуществующей 'resourceID', то они оба могут попытаться создать новый замок. Надеюсь, это не проблема или вы знаете об этом. Непонятно, почему вам нужны блокировки для доступа ресурсов. Вы можете ускорить доступ, используя кеш (если это была цель). В противном случае, не зная, используется ли ресурс или нет, нормально ли его освобождать? Если да, повторите кеширование. Храните время последнего доступа для каждого ресурса, проверяйте (периодически или добавляя новый ресурс) для него, бесплатно, когда истек. – Sinatr

+0

Эти ресурсы предназначены не только для чтения, но и для некоторых модификаций, поэтому я буду хранить блокировку записи, чтобы не читать ее в это время. (например, файловый ресурс) – ineztia

ответ

2

Вы можете попробовать использовать ConditionalWeakTable вместо ConcurrentDictionary. ConditionalWeakTable автоматически удаляет значение . из словаря, когда ее ключ был собран сборщиком мусора

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(); 
} 
+0

Блестящий! BTW У меня есть вопрос, для какого-то не-ссылочного ресурса, такого как кешированное целочисленное значение или строковое содержимое (так что Key of WeakTable не является объектом), он все еще работает? @Wazner – ineztia

+0

Нет, ConditionalWeakTable требует, чтобы его ключ был ссылочным типом (которого нет целого числа). И хотя строка является ссылочным типом, она не рекомендуется, потому что их время жизни трудно предсказать из-за [string interning] (https://en.wikipedia.org/wiki/String_interning) в .NET. – Wazner