2009-12-22 13 views
15

Ich versuche, einen Überblick über die Threadsicherheitstheorie hinter den Sammlungen in C# zu bekommen.Warum gibt es in C# keine gleichzeitigen Sammlungen?

Warum gibt es keine gleichzeitigen Sammlungen wie in Java? (java docs). Einige Sammlungen erscheinen Thread-sicher, aber es ist mir nicht klar, was die Position zum Beispiel im Hinblick auf:

  • Verbindung Operationen,
  • Sicherheit der Verwendung Iteratoren
  • Schreiboperationen

Ich will das Rad nicht neu erfinden! (Ich bin kein Multithreading-Guru und unterscheide definitiv nicht, wie schwer das sowieso wäre).

Ich hoffe, die Gemeinde kann helfen.

+0

Große Antwort - ich werde dieses "unbeantwortete" für eine kurze Zeit verlassen, um es auf dem Radar zu halten. Wenn jemand weitere Links zu Artikeln über Pre- oder Post-4.0-Status zu diesem Thema hat, dann bitte. Danke euch allen. – Andrew

Antwort

28

.NET hat bisher relativ „niedrigem Niveau“ Gleichzeitigkeit Unterstützung hatte - aber .NET 4.0 stellt den System.Collections.Concurrent Namespace, die verschiedene Sammlungen enthält, die sicher und nützlich sind.

Andrew Antwort ist völlig korrekt in Bezug auf den Umgang mit Sammlungen vor .NET 4.0 natürlich - und für am meisten verwendet ich würde nur richtig sperren beim Zugriff auf eine "normale" gemeinsame Sammlung. Die gleichzeitigen Auflistungen erleichtern jedoch die Verwendung einer Erzeuger/Verbraucher-Warteschlange usw.

+0

+1 danke Jon. Ich schätze, dass .net Leute nicht in ein falsches Gefühl von Sicherheit bringt. Ich werde die .Net 4.0-Goodies auschecken. - Andrew – Andrew

+0

+1 Schön, vergaß alles darüber :) –

19

C# bietet mehrere Möglichkeiten zum Arbeiten mit Sammlungen über mehrere Threads hinweg.

Standardmäßig sind Sammlungen Klassen nicht generell fädeln sicher: Für eine gute Zuschreibung von diesen Techniken würde ich, dass Sie mit Collections and Synchronization (Thread Safety) beginnen empfehlen. Mehrere Leser können die Sammlung mit Vertrauen lesen; Jede Änderung an die Auflistung erzeugt jedoch undefined Ergebnisse für alle Threads, die die Auflistung zugreifen, einschließlich der Leser Threads.

Collections Klassen können aus Faden mit einer der folgenden Methoden sicher:

  • erstellen threadsicher Wrapper mit der synchronisierte Methode und Zugriff die Sammlung ausschließlich durch diese Umhüllung.
  • Wenn die Klasse keine Synchronized-Methode hat, leiten Sie sie von der -Klasse ab und implementieren Sie eine synchronisierte -Methode mit der SyncRoot-Eigenschaft.
  • Verwenden Sie einen Sperrmechanismus, z. B. die Lock-Anweisung in C# (SyncLock in Visual Basic) auf der SyncRoot -Eigenschaft beim Zugriff auf die Sammlung.
+0

+1 das war schnell! - Das sieht ein bisschen wie die Collections.synchronizedList von Java aus. Ich werde diesen Link überprüfen. Danke – Andrew

+4

Und siehe auch hier: http://blogs.msdn.com/ericlippert/archive/2008/01/21/immutability-in-c-part-nine-academic-plus-my-avl-tree-implementation.aspx Dort diskutiert Eric Lippert unveränderliche Sammlungen eingehend, insbesondere im Hinblick auf den gleichzeitigen Zugriff. –

+0

Dank Jeremy war nicht über diesen Blog gekommen (jetzt abonniert) gibt es einige ausgezeichnete Material unter dem Tag der Unveränderlichkeit. – Andrew

6

Wie bereits von Jon Skeet erwähnt, gibt es jetzt im System.Collections.Concurrent-Namespace in .NET 4. "

" Thread-sichere Auflistungen

Einer der Gründe, dass keine gleichzeitige Sammlungen existieren (zumindest meine Vermutung) in früheren.NET Framework-Versionen ist es sehr schwierig, Thread-Sicherheit zu garantieren, selbst bei gleichzeitiger Sammlung.

(Dies ist nicht ganz richtig, da einige Sammlungen ein synchronisiertes Verfahren bieten einen Thread sichere Sammlung von einer nicht-Thread-sicher Sammlung zurück, so gibt es einige Thread sichere Sammlungen sind ...)

Zum Beispiel davon ausgehen, man hat ein threadsicheres Dictionary - wenn man nur zu einer Einfügung möchte, wenn der Schlüssel nicht existiert, würde man zuerst die Sammlung abfragen, um zu sehen, ob der Schlüssel existiert, dann würde man eine Einfügung machen, wenn der Schlüssel nicht existiert. Diese beiden Operationen sind jedoch nicht Thread-sicher, da zwischen der Abfrage von ContainsKey und der Add-Operation ein anderer Thread eine Einfügung dieses Schlüssels hätte durchführen können, so dass es eine Race-Bedingung gibt.

Mit anderen Worten sind die Operationen der Sammlung threadsicher - aber die Verwendung ist nicht unbedingt notwendig. In diesem Fall müsste man zu traditionellen Verschlusstechniken (Mutex/Monitor/Semaphore ...) zurückkehren, um Thread-Sicherheit zu erreichen, so dass die gleichzeitige Sammlung nichts in Bezug auf Multithread-Sicherheit gekauft hat (ist aber wahrscheinlich schlechter für die Leistung) .

+0

Ich dachte in die gleiche Richtung. Das Put-If-Abwesend-Problem, bei dem Sie mit 2 Objekten in Ihrer Sammlung enden konnten, in denen es zuvor noch keine gab. Danke +1. – Andrew

+0

@aret: Wie schwer ist es wirklich, die Funktionen bereitzustellen, die für eine echte thread-sichere Verwendung benötigt werden? Ich würde denken, wenn das Wörterbuch keine "Nothing" -Werte enthalten müsste, könnte alles mit einem Enumerator, einer Long-Change-Count-Eigenschaft und einer Methode, die analog zu Threading.Interlocked.CompareExchange funktionierte, durchgeführt werden. Hinzufügen von "Nothing" -Werten schafft ein wenig mehr Komplexität, aber nicht zu viel. – supercat

+0

@supercat, ein möglicherweise besserer Weg ist, Methoden für die Sammlung selbst anzubieten, die innerhalb einer Sperre funktionieren (z. B. Aktion/Funktion innerhalb der Sperre ausführen) oder Funktionen wie InsertIfNotExists anbieten – saret

Verwandte Themen