Für .NET 3.5 wie würden Sie einen thread-sicheren Cache erstellen oder hinzufügen?

8

Ich habe angefangen, mit etwas .NET 3.5 Code zu arbeiten und fand die folgende Erweiterungsmethode für einen Cache ::

%Vor%

Der betreffende Cache wird mit Stringschlüsseln und mit useLocking = true verschlüsselt. Auf diese Methode wird immer zugegriffen (es gibt kein stray TryGetValue ). Es gibt auch kein Problem bei der Verwendung der Eigenschaft SyncRoot , da das Wörterbuch privat ist und nirgendwo anders verwendet wird. Die doppelte Sperre ist gefährlich, da ein Wörterbuch das Lesen während des Schreibens nicht unterstützt. Obwohl technisch noch kein Problem gemeldet wurde, da das Produkt nicht ausgeliefert wurde, glaube ich, dass dieser Ansatz zu Rennbedingungen führen wird.

  1. Schalte Dictionary<,> auf Hashtable um. Wir werden die Typensicherheit verlieren, aber wir werden in der Lage sein, das von uns angestrebte Nebenläufigkeitsmodell zu unterstützen (1 Autor, mehrere Leser).

  2. Entfernen Sie den äußeren TryGetValue. Auf diese Weise muss jeder Lesevorgang eine Sperre erhalten. Dies ist möglicherweise schlecht für die Leistung, aber eine unangekündigte Sperre sollte ziemlich billig sein.

Beide sind ziemlich beschissen. Hat jemand einen besseren Vorschlag? Wenn dies .NET 4-Code wäre, würde ich es nur auf ein ConcurrentDictionary umstellen, aber ich habe diese Option nicht.

    
Michael B 17.12.2010, 19:01
quelle

4 Antworten

2

Ja, Ihr Verdacht ist richtig; Es gibt eine Race-Bedingung und alle Methoden, auch TryGetValue , müssen in der von Ihnen dargestellten Implementierung in der Sperre sein.

Was die Leistung angeht, können Sie sich auf den Tag freuen, an dem Sie auf .NET4 upgraden können, der ein "schreiendes schnelles ConcurrentDictionary out of the box" enthält. Bis dahin können Sie die hier durchgeführte Analyse von James Michael Hare überprüfen:

Diese Ergebnisse legen nahe, dass die beste Implementierung für .NET3% Dictionary plus ReadWriteLockSlim ist, und hier ist eine vollständige Implementierung:

Aktualisierung:

Ich lese die Tabellen falsch und es sieht so aus, als wäre Dictionary + lock etwas schneller als der einzige andere ernsthafte Konkurrent Dictionary + ReadWriteLockSlim .

    
Rick Sladkey 31.12.2010 05:42
quelle
1

Meine Empfehlung wäre, Reaktive Erweiterungen für .NET (Rx) herunter zu laden, die Backports von enthält die Auflistungen im Namespace System.Collections.Concurrent (einschließlich ConcurrentDictionary<TKey, TValue> ) für .NET 3.5.

    
Dan Tao 31.12.2010 06:21
quelle
0

Entfernen Sie den TryGetValue. Ich wette, Sie werden das Nebenläufigkeitsproblem nicht sehen; CLR-Monitore sind ziemlich schnell und "unfair", so dass Konvoi oder Prioritätsinversionsprobleme nicht auftreten.

Wenn Sie ein Nebenläufigkeitsproblem sehen, dann ist die nächstbeste Sache ein ReaderWriterLockSlim. Leider werden Sie dafür eine neue Klasse erstellen müssen, anstatt eine Erweiterungsmethode zu verwenden, da Sie einen Speicherort für die Sperre benötigen.

Wenn Sie diese Route gehen, sollten Sie sich von der Aktualisierung von Lese- auf Schreibschutz sperren lassen.

    
John Doty 27.12.2010 16:42
quelle
0

Ich denke, dass Sie die komplette Aussage sperren müssen (wie Sie sagten).

Es gibt jedoch eine saubere Lösung im Web, die für ein zukünftiges .NET 4-Upgrade vorbereitet wird: Sie haben eine benutzerdefinierte Klasse anstelle eines Wörterbuchs, behalten das Wörterbuch als private Membervariable und umschließen den gesamten Zugriff auf das Wörterbuch in einem Thread- Safe Lock-Anweisung. Detaillierte Beschreibung finden Sie hier: Ссылка

    
thoean 30.12.2010 13:37
quelle

Tags und Links