.NET-Thread-Sicherheit

8

List.Add ist ein Instanzmitglied. Das bedeutet, dass es nicht garantiert ist, threadsicher zu sein. Was bedeutet das?

Möglichkeit 1. Wenn zwei Threads auf verschiedene Instanzen zugreifen, kann es je nach Mondphase zu unerwarteten Ergebnissen kommen.

Möglichkeit 2. Wenn zwei Threads auf dieselbe Instanz zugreifen, kann es je nach Mondphase zu einem unerwarteten Ergebnis kommen, und wenn die Instanzen unterschiedlich sind, besteht kein potenzielles Problem.

Möglichkeit 3. Microsoft möchte nicht, dass Leute Threading überhaupt verwenden, also schrieben sie .NET, um mehrdeutig zu sein.

    
H2ONaCl 23.08.2010, 01:42
quelle

5 Antworten

10

Möglichkeit 1 ist nicht der Fall. Es wäre so ungewöhnlich, dass eine Instanzmethode anderen Instanzen Probleme bereiten würde, dass dies eindeutig dokumentiert wäre (nicht nur mit einer Aussage, die darauf hinweist, sondern auch mit einer gewissen Begründung, da dies im Allgemeinen ein Zeichen für eine sehr schlechte Codierung wäre es gab einen guten Grund dafür, darauf wurde hingewiesen).

Möglichkeit 3 ​​ist nicht der Fall, da sie das Threading-Verhalten gerade dokumentiert haben.

Möglichkeit 2 ist teilweise der Fall. Die Interaktion kann jedoch auch mit einem Thread erfolgen, der Add aufruft, und einem anderen Aufruf einer anderen Nicht-ThreadSafe-Instanzmethode.

Die Mehrheit der veränderbaren Klassen, die vom Framework bereitgestellt werden, sind Threadsafe für statische Member und Nicht-Thread-Safe für Instanzmethoden. Dies ist aus gutem Grund.

  1. Wenn eine statische Methode nicht threadsicher ist, ist es sehr schwierig, auf diese Weise threadsicher auf diese Methode zuzugreifen, insbesondere wenn die Klasse von verschiedenen Codeebenen verwendet werden kann, die von verschiedenen Personen geschrieben wurden. Dies macht den Aufwand, solche Methoden threadsicher zu machen, fast immer gerechtfertigt. Die meisten solcher Mitglieder sind auch relativ einfach, threadsafe zu machen (wenn man vermeidet, veränderlichen statischen Zustand zu haben, was immer eine gute Sache zu vermeiden ist).

  2. Die einzelnen Objekte werden häufig einzeln verwendet, ohne dass ein anderer Thread darauf zugreifen kann. Dies macht es schwierig, die Korrektheit zu gewährleisten, wobei das Risiko eines Deadlocks, wenn es schief geht, und der Overhead, der der Performance auferlegt wird, schwer zu rechtfertigen sind. Es ist auch relativ einfach für die Person, die die Klasse verwendet, sicherzustellen, dass eine Instanz, die von mehreren Threads verwendet wird, threadsicher verwendet wird.

Es gibt eine starke Betonung auf das "relativ" da, da das Schreiben von threadsafe Code nicht immer einfach ist. Manchmal ist es ziemlich einfach (unveränderliche Klassen nehmen ein wenig Arbeit, um nicht-threadsafe zu machen!), Aber öfter ist es sehr schwierig (daher viele Fragen zum Thema hier und anderswo).

Aber gerade deshalb sollte in solchen Fällen der Benutzer belastet werden. Eine solche Klasse vollständig threadsicher zu machen, ist so schwierig (manchmal sogar nachweislich unmöglich), dass die Ergebnisse für die meisten Benutzer inakzeptabel sind, denn sie sind diejenigen, die am besten beurteilen können, welcher Schutz in einem bestimmten Fall erforderlich ist.

>     
Jon Hanna 23.08.2010, 02:19
quelle
4

Ich denke, List.Add ist ein schlechtes Beispiel. List.Remove ist viel besser, weil es tatsächlich bemerkenswerte Threading-Probleme gibt. Ein Thread könnte versuchen, auf ein Element zuzugreifen, während ein anderer Thread versuchen würde, List.Remove aufzurufen. Nun könnte es passieren, dass das Objekt entfernt wird, wenn versucht wird, darauf zuzugreifen, was zu einem NullReferenceException führt. Im Allgemeinen ist dies jedoch meist ein Haftungsausschluss, da es keine Sperrmechanismen gibt. Denken Sie daran, dass lock immer dann verwendet wird, wenn zwei Threads versuchen könnten, auf dasselbe Objekt oder denselben Code zuzugreifen, um solche Probleme zu vermeiden.

    
Femaref 23.08.2010 01:48
quelle
0

Da kein Sperrmechanismus für Instanzmitglieder implementiert ist, wird dieser Haftungsausschluss auf der MSDN-Website angezeigt.

Siehe auch Statik und Fadensicherheit

und Statik und Fadensicherheit: Teil II

    
user195488 23.08.2010 01:46
quelle
0

Wenn zwei Threads gleichzeitig versuchen, verschiedene Dinge mit der gleichen Instanz einer Liste zu tun, können schlimme Dinge passieren. Die einzige Situation, in der es für mehrere Threads sicher ist, gleichzeitig verschiedene Dinge mit einer Liste zu tun, ist, wenn alle Threads lesen. Ich denke, das ist sicher mit einer Liste, obwohl das nicht unbedingt mit allen Container-Klassen sicher ist.

Sammlungen wie Listen in .net werden im Allgemeinen in Arrays gespeichert; Wenn eine Sammlung für ihr Array zu groß wird, wird ein größeres Array zugewiesen. Wenn mehrere Threads mit derselben Auflistung arbeiten und keine Interlocks aufweisen, ist es möglich, dass ein Thread etwas hinzufügt, das eine Liste wachsen lässt, und dass andere Threads versuchen, die Liste zwischen dem Zeitpunkt der Liste zu ändern kopiert und die Zeit, zu der die Sammlung begann, mit der neuen Liste. Dies kann dazu führen, dass Änderungen verloren gehen oder andere schlimme Dinge passieren.

    
supercat 23.08.2010 02:05
quelle
0

Wenn zwei verschiedene Threads dieselbe Liste ohne Synchronisierung / Sperrung ändern, kann dies zu Problemen führen. Zwei Threads, die mit verschiedenen Listen arbeiten, sind in Ordnung. Dasselbe gilt für die meisten Klassen - es gibt tatsächlich sehr, sehr wenige Klassen, die explizit angeben, dass "diese Klasse threadsicher ist", aber fast alle sind sicher, wenn Sie Instanzen zwischen Threads nicht freigeben (auf sie zugreifen). Wenn eine Klasse bricht, selbst wenn Threads keine Instanzen teilen, wird dies von den Dokumenten gesagt - aber das ist so eine hässliche Situation, dass ich hoffen würde, dass MS sie aus der API heraushalten würde.

Microsoft sagt und macht die Dinge so, wie sie es tun (aus Gründen der Thread-Sicherheit):

Fadensicherheit ist schwer.

Es gibt keine Möglichkeit, Dinge zu synchronisieren, die für alle funktionieren. Und das Sperren und Synchronisieren, wenn Sie nicht müssen, kann die Leistung und möglicherweise sogar die Stabilität beeinträchtigen. Die allumfassend beste Lösung ist, dass der Code einfach das tut, was er tun soll, ohne Synchronisierung, und die Leute, die Thread-Sicherheit brauchen, können sie selbst arrangieren.

    
cHao 23.08.2010 02:05
quelle

Tags und Links