2016-03-31 3 views
1

ein Wörterbuch von ReaderWriterLockSlim Objekten für den Ressourcenzugriff beibehalten: (Beispielcode ist hier hässlich, nur machen Sie meinen Zweck verstehen)(C#) Auto GC möglich Wörterbuch machen <ReaderWriterLockSlim>

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

Und verwenden wie dies:

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

Ressourcen können dynamisch hinzugefügt oder entfernt werden und deren Lebenszyklus ist unberechenbar (nicht in der Lage Entfernung von Ressource mornitor), als Menge an Ressourcen aufwächst, Größe rwResourceLocks wird zu Erhöhung, die in den Speicher führen Ärger. Gibt es eine Möglichkeit, dieses Problem zu lösen? (Natürlich kann ich nicht einfach anrufen rwResourceLocks.Clear(), dies zu tun)

Ich weiß, es ist ein bisschen kompliziert :(

+0

Es gibt eine race-Bedingung: wenn zwei Threads für gleiche nicht vorhandene 'resourceID' prüfen, werden dann sie beide versuchen, neue Sperre zu erstellen. Hoffentlich ist das kein Problem oder Sie sind sich dessen bewusst. Es ist nicht klar, warum Sie Sperren für Zugriffe benötigen s Ressourcen. Sie können den Zugriff beschleunigen, indem Sie einen Cache implementieren (wenn das ein Ziel war). Andernfalls, ohne zu wissen, ob die Ressource verwendet wird oder nicht, ist es in Ordnung, sie freizugeben? Wenn ja, dann erneut zwischenspeichern. Speichern Sie die letzte Zugriffszeit für jede Ressource, überprüfen Sie (periodisch oder beim Hinzufügen einer neuen Ressource), wann sie abgelaufen ist. – Sinatr

+0

coz diese Ressourcen sind nicht nur zum Lesen, aber manchmal geändert, ich werde eine Schreibsperre halten, um zu verhindern, dass es zu diesem Zeitpunkt zu lesen. (z. B. eine Datei-Ressource) – ineztia

Antwort

2

Sie könnten versuchen, eine ConditionalWeakTable anstelle eines ConcurrentDictionary verwenden. Ein ConditionalWeakTable entfernt automatisch einen Wert . aus dem Wörterbuch, wenn seine Schlüssel von der Garbage Collector gesammelt worden

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

Brilliant! BTW Ich habe eine Frage, für einige Nicht-Referenz-Ressource wie Cache-Integer-Wert oder Zeichenfolge Inhalt (also Key of WeakTable ist kein Objekt), funktioniert es noch? @Wazner – ineztia

+0

Nein, ConditionalWeakTable benötigt seinen Schlüssel als Referenztyp (was eine Ganzzahl nicht ist). Und obwohl eine Zeichenfolge ein Referenztyp ist, wird sie nicht empfohlen, da ihre Lebensdauer aufgrund von [string interning] (https://en.wikipedia.org/wiki/String_interning) in .NET schwer vorherzusagen ist – Wazner

Verwandte Themen