2010-02-08 12 views
6

Diese Frage bezieht sich auf ein sehr spezifisches und häufiges Szenario, in dem ein Wörterbuch für das On-Demand-Caching von Elementen in einer Multithread-Umgebung verwendet wird. Um Thread-Locking zu vermeiden, ist es besser, nach einem bestehenden Cache-Element außerhalb einer Synchronisationssperre zu suchen, aber wenn wir anschließend ein Element hinzufügen müssen, zählt das als ein Schreiben in das Wörterbuch und daher ist der beste Rat, den ich auf Stackoverflow gelesen habe Sie müssen sowohl den Lese- als auch den Schreibvorgang sperren, da der interne Status des Wörterbuchs möglicherweise durch die Aufrufe von add() geändert wird.Ist ein Dictionary <K,V> Thread für simultanes Lesen und Addieren sicher?

Wenn Sie jedoch durch Microsofts AjaxControlToolkit (scriptObjectBuilder-Klasse) suchen, führt der Code TryGet() außerhalb von Sperren aus und sperrt nur neue Elemente (Add) zum Wörterbuch. Ich kann sehen, wie das möglich ist, wenn der Eimer, in den ein Gegenstand gelegt wird, sich nie ändert, sobald er hinzugefügt wird, aber mein Verdacht ist, dass dies falsch ist und eine Quelle von Fehlern sein könnte.

Danke.

UPDATE Gehen durch die .Net-Dokumentation Ich denke, dass das beschriebene Muster in der Tat falsch ist. Allerdings habe ich mich gefragt, ob die spezielle Implementierung von Dictionary es erlaubt und dass das AjaxControlToolkit darauf angewiesen ist (was zweifelhaft wäre). Bei der Überprüfung des Codes in Reflector bin ich mir ziemlich sicher, dass dies in der Tat falsch ist, die Dictionary.Resize() -Methode weist die Anzahl der Buckets neu zu und verschiebt Bucket-Elemente umher, sodass jeder Thread in der Mitte eines TryGet() möglicherweise funktionieren könnte auf instabilen Daten.

UPDATE Ein Fehler wurde bereits gegen das AjaxControlToolkit auf Codeplex protokolliert. Siehe:

+0

haben Sie es versucht? Client-seitiges Scripting ist normalerweise single-threaded. Standardvorbehalte gelten. –

+0

Haben Sie schon einmal versucht, ein Testkabel zu schreiben? Ich wäre interessiert zu sehen, ob dies auch ein Problem verursacht. –

+0

Dies ist der Ajax-Code auf der Serverseite.Es gibt Thread-Sync's, weil es an Orten statische Dictionary verwendet, um Daten zwischenzuspeichern. – redcalx

Antwort

-1

Um meine eigene Frage nach einiger Investition zu beantworten: Beim Untersuchen des Codes für Dictionary kann ich sehen, dass die Dictionary.Resize() -Methode die Anzahl der internen Buckets zum Speichern von Daten neu zuordnet und den Bucket-Inhalt neu verteilt Die Elemente befinden sich basierend auf ihrem Hashcode im richtigen Bucket. Somit riskiert jeder Thread in der Mitte von TryGet() die Arbeit an instabilen Daten.

Nebenbei, eine mögliche Low-Locking-Ansatz für eine Dictionary-Klasse könnte sein, eine Sperre um nur die Resize() -Methode zu platzieren.

+0

Die Antwort von Rex M ist korrekter und ich habe diese im Produktionscode gefunden. Synchronisieren Sie die gesamte Sache, es sei denn * jeder * Thread ist schreibgeschützt. ReaderWriterLock [Slim] ist angemessen. – FMM

5

Tess Ferrandez eine excellent blog post über Threadingprobleme mit generischem Wörterbücher hat:

die FindEntry Methode Wörterbuch geht durch und versuchte, den Schlüssel zu finden . Wenn mehrere Threads dies gleichzeitig tun, insbesondere wenn das Dictionary in der Zwischenzeit geändert wird, können Sie in FindEntry in einer Endlosschleife landen, die das hohe CPU-Verhalten verursacht, und der Prozess kann hängen.

1

Ich würde sagen, das ist definitiv ein Fehler im AjaxControlToolkit, und würde Ihnen empfehlen, einen Fehler auf CodePlex zu melden. Es sollte einen ReaderWriteLock (Slim) verwenden.

+0

Danke. Anscheinend war es bereits 2007 eingeloggt, aber ich habe etwas Input hinzugefügt. Siehe Links in der Post (oben nach oben) – redcalx