Ist es in Ordnung, System.Collections.Generic.Listt zu sperren?

8

Ich habe über das syncroot-Element gelesen, aber ich kann es nicht im List-Typ finden. Wie sollte also die Multithreading-Synchronisation mit der System.Collections.Generic.List & lt; & gt; eingeben?

    
Karim 14.11.2009, 18:06
quelle

5 Antworten

11

Der Grund, warum Sie es nicht finden können, ist, dass explizit entfernt wurde . Wenn es wirklich das ist, was Sie tun möchten, verwenden Sie SynchronizedCollection<T> oder erstellen Sie ein dediziertes Synchronisationsobjekt. Der beste Ansatz (im Allgemeinen) besteht darin, ein dediziertes Synchronisationsobjekt zu erstellen, wie Winston veranschaulicht.

Das wesentliche Problem mit der Eigenschaft SyncRoot ist, dass es ein falsches Gefühl der Sicherheit bietet - es behandelt nur eine sehr begrenzte Anzahl von Umständen. Entwickler vernachlässigen oft die Synchronisation für eine gesamte logische Operation, wenn man annimmt, dass das Sperren auf SyncRoot gut genug ist.

Sie möchten generell verhindern, dass ein Typ gesperrt wird ( List<T> in diesem Fall). Wenn Sie beispielsweise zwei Instanzen Ihres Typs haben oder ein anderer Typ eine Sperre für List<T> verwenden würde, würden alle um eine einzelne globale Sperre konkurrieren. Wirklich, was Sie erreichen wollen, ist die richtige Synchronisation für ein einzelnes Objekt.

    
Nader Shirazie 14.11.2009, 18:52
quelle
10

Warum möchten Sie List<T> im Gegensatz zu Ihrer spezifischen Instanz einer Liste sperren?

Es wird oft vorgeschlagen, dass die beste Methode zum Sperren das Sperren eines privaten Objekts ist, das ausschließlich für diesen Zweck erstellt wurde.

%Vor%

Eine gute Anleitung zum Einfädeln von C # finden Sie in diesem freien E-Book (Threading in C #) von Joe Albahari.

    
Winston Smith 14.11.2009 18:37
quelle
7

Sie müssen die generische Liste in ein ICollection wie folgt umwandeln:

%Vor%

Beachten Sie, dass damit nur der Zugriff auf die Elemente der generischen Liste synchronisiert wird. nicht synchronisiert den Zugriff auf die generische Listenvariable, z. B. myIntList . Wenn Sie myIntList irgendwann durch eine neue Liste ersetzen, reicht die Verwendung von SyncRoot nicht aus. In diesem Fall würde ich empfehlen, ein spezifisches Synchronisationsobjekt zu erstellen, das für beide Synchronisationsszenarien verwendet werden kann.

    
Matt Davis 14.11.2009 18:35
quelle
2

Die Antwort lautet Ja. Sie können eine Instanz der Liste als Synchronisierungsobjekt verwenden:

%Vor%

Sie müssen also die SyncRoot-Eigenschaft nicht verwenden. Darüber hinaus Dokumentation heißt das

  

Für Sammlungen, deren zugrunde liegender Store nicht öffentlich verfügbar ist, wird der   erwartete Implementierung ist, die aktuelle Instanz zurückzugeben.

d. In einigen Fällen gibt die SyncRoot-Eigenschaft das Auflistungsobjekt selbst zurück.

Lesen Sie auch diese Antwort zu SyncRoot.

Zu Ihrer Information: Ich habe SyncRoot-Usages im Produktionscode noch nie gesehen. Daher empfehle ich Ihnen, die Instanz einer beliebigen Sammlung als Synchronisierungsobjekt anstelle der SyncRoot-Eigenschaft zu verwenden (solange die Sammlung privat ist).

    
Lu55 25.11.2016 17:31
quelle
0

Schauen Sie hier ("Gleichzeitige Sammlungen in C #").

    
Hannoun Yassir 14.11.2009 18:17
quelle

Tags und Links