Gibt es allgemeine Regeln / Richtlinien dafür, was eine Methode threadsicher macht? Ich verstehe, dass es wahrscheinlich eine Million einmaliger Situationen gibt, aber was ist im Allgemeinen? Ist es so einfach?
- Wenn eine Methode nur auf lokale Variablen zugreift, ist sie threadsicher.
Ist es das? Gilt das auch für statische Methoden?
Eine Antwort von @Cybis lautete:
Lokale Variablen können nicht von Threads gemeinsam genutzt werden, da jeder Thread seinen eigenen Stapel erhält.
Gilt das auch für statische Methoden?
Wenn einer Methode ein Referenzobjekt übergeben wird, bricht dies die Thread-Sicherheit? Ich habe einige Nachforschungen angestellt, und es gibt eine Menge über bestimmte Fälle, aber ich hatte gehofft, mit nur wenigen Regeln Richtlinien definieren zu können, die befolgt werden müssen, um sicherzustellen, dass eine Methode threadsicher ist.
Meine letzte Frage lautet also: "Gibt es eine kurze Liste von Regeln, die eine thread-sichere Methode definieren? Wenn ja, welche?"
BEARBEITEN
Hier wurden viele gute Punkte gemacht. Ich denke, die eigentliche Antwort auf diese Frage lautet: "Es gibt keine einfachen Regeln, um die Thread-Sicherheit zu gewährleisten." Cool. Fein. Aber im Allgemeinen denke ich, dass die akzeptierte Antwort eine gute, kurze Zusammenfassung liefert. Es gibt immer Ausnahmen. So sei es. Ich kann damit leben.
quelle
Antworten:
Wenn eine Methode (Instanz oder statisch) nur auf Variablen verweist, die in dieser Methode enthalten sind, ist sie threadsicher, da jeder Thread seinen eigenen Stapel hat:
In diesem Fall können mehrere Threads
ThreadSafeMethod
gleichzeitig ohne Probleme aufgerufen werden.Dies gilt auch, wenn die Methode eine andere Klassenmethode aufruft, die nur auf Variablen mit lokalem Gültigkeitsbereich verweist:
Wenn eine Methode auf Eigenschaften oder Felder (Objektstatus) (Instanz oder statisch) zugreift, müssen Sie Sperren verwenden, um sicherzustellen, dass die Werte nicht von einem anderen Thread geändert werden.
Sie sollten sich bewusst sein, dass alle an die Methode übergebenen Parameter, die weder eine Struktur noch unveränderlich sind, von einem anderen Thread außerhalb des Bereichs der Methode mutiert werden können.
Um eine ordnungsgemäße Parallelität sicherzustellen, müssen Sie die Sperrung verwenden.
Weitere Informationen finden Sie in der C # -Referenz der Sperranweisung und in ReadWriterLockSlim .
Die Sperre ist meistens nützlich, um Funktionen nacheinander
ReadWriterLockSlim
bereitzustellen. Sie ist nützlich, wenn Sie mehrere Leser und einzelne Schreiber benötigen.quelle
private string someValue;
ist nichtstatic
so, dass jede Instanz eine separate Kopie dieser Variablen erhält. Können Sie bitte erklären, warum dies nicht threadsicher ist?Thing
Klasse gibt, auf die mehrere Threads zugreifenAbsolut nicht. Sie können ein Programm mit nur einer lokalen Variablen schreiben, auf die von einem einzelnen Thread aus zugegriffen wird, der jedoch nicht threadsicher ist:
https://stackoverflow.com/a/8883117/88656
Absolut nicht.
Absolut nicht. Das Unterscheidungsmerkmal einer lokalen Variablen besteht darin, dass sie nur innerhalb des lokalen Bereichs sichtbar ist und nicht im temporären Pool zugeordnet ist . Es ist völlig legal und möglich, von zwei verschiedenen Threads auf dieselbe lokale Variable zuzugreifen. Sie können dazu anonyme Methoden, Lambdas, Iteratorblöcke oder asynchrone Methoden verwenden.
Absolut nicht.
Vielleicht.
Sie müssen lernen, mit Enttäuschung zu leben. Dies ist ein sehr schwieriges Thema.
Nee. Wie Sie in meinem Beispiel zuvor gesehen haben, kann eine leere Methode nicht threadsicher sein . Sie können auch fragen, ob es eine kurze Liste von Regeln gibt, die sicherstellen, dass eine Methode korrekt ist . Nein, da ist kein. Die Gewindesicherheit ist nichts anderes als eine äußerst komplizierte Art der Korrektheit.
Darüber hinaus weist die Tatsache, dass Sie die Frage stellen, auf Ihr grundlegendes Missverständnis hinsichtlich der Thread-Sicherheit hin. Die Thread-Sicherheit ist eine globale und keine lokale Eigenschaft eines Programms. Der Grund, warum es so schwierig ist, das Richtige zu finden, liegt darin, dass Sie das Threading-Verhalten des gesamten Programms vollständig kennen müssen, um seine Sicherheit zu gewährleisten.
Schauen Sie sich noch einmal mein Beispiel an: Jede Methode ist trivial . Es ist die Art und Weise, wie die Methoden auf einer "globalen" Ebene miteinander interagieren, die das Programm zum Stillstand bringt. Sie können nicht jede Methode betrachten und als "sicher" abhaken und dann erwarten, dass das gesamte Programm sicher ist, genauso wenig wie Sie daraus schließen können, dass Ihr Haus auch aus 100% nicht hohlen Ziegeln besteht nicht hohl. Die Hohlheit eines Hauses ist ein globales Eigentum des Ganzen, kein Aggregat der Eigenschaften seiner Teile.
quelle
class C { public static Func<int> getter; public static Action<int> setter; public static void M() { int x = 0; getter = ()=>x; setter = y=>{x=y;};} }
Rufen Sie M () auf und rufen Sie dann C.getter und C.setter in zwei verschiedenen Threads auf. Die lokale Variable kann jetzt in zwei verschiedene Threads geschrieben und daraus gelesen werden, obwohl es sich um eine lokale Variable handelt. Nochmals: Das definierende Merkmal einer lokalen Variablen ist, dass sie lokal ist und nicht auf dem Stapel des Threads .Es gibt keine feste Regel.
Hier sind einige Regeln, um den Code-Thread in .NET sicher zu machen und warum dies keine guten Regeln sind:
lock
mit einer gemeinsamen Sache arbeiten. Alle Sperren müssen in derselben Reihenfolge erfolgen. Dadurch wird der Code-Thread sicher, aber er ist unglaublich langsam, und Sie können genauso gut nicht mehrere Threads verwenden.Es gibt keine Regel, die den Code-Thread sicher macht. Sie können nur sicherstellen, dass Ihr Code funktioniert, egal wie oft er aktiv ausgeführt wird. Jeder Thread kann zu jedem Zeitpunkt unterbrochen werden, wobei sich jeder Thread befindet seinen eigenen Zustand / Ort, und dies für jede Funktion (statisch oder anderweitig), die auf allgemeine Objekte zugreift.
quelle
Es muss mithilfe einer Objektsperre synchronisiert werden, zustandslos oder unveränderlich.
Link: http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
quelle