Kürzlich habe ich versucht, von einem Thread (außer dem UI-Thread) auf ein Textfeld zuzugreifen, und es wurde eine Ausnahme ausgelöst. Es sagte etwas über den "Code ist nicht threadsicher" aus und so schrieb ich einen Delegaten (Beispiel von MSDN half) und rief ihn stattdessen auf.
Trotzdem verstand ich nicht ganz, warum der ganze zusätzliche Code notwendig war.
Update: Treten bei einer Überprüfung ernsthafte Probleme auf?
Controls.CheckForIllegalCrossThread..blah =true
multithreading
thread-safety
definition
Vivek Bernard
quelle
quelle
Race-Condition
Antworten:
Eric Lippert hat einen schönen Blog-Beitrag mit dem Titel Was nennst du "thread safe"? über die Definition der Thread-Sicherheit aus Wikipedia.
3 wichtige Dinge aus den Links extrahiert:
Auf jeden Fall eine Lektüre wert!
quelle
Im einfachsten Sinne bedeutet threadsafe, dass der Zugriff von mehreren Threads sicher ist. Wenn Sie mehrere Threads in einem Programm verwenden und diese jeweils versuchen, auf eine gemeinsame Datenstruktur oder einen Speicherort im Speicher zuzugreifen, können mehrere schlechte Dinge passieren. Sie fügen also zusätzlichen Code hinzu, um diese schlechten Dinge zu verhindern. Wenn beispielsweise zwei Personen gleichzeitig dasselbe Dokument schreiben, überschreibt die zweite zu speichernde Person die Arbeit der ersten Person. Um den Thread dann sicher zu machen, müssen Sie Person 2 zwingen, darauf zu warten, dass Person 1 ihre Aufgabe erledigt, bevor Person 2 das Dokument bearbeiten kann.
quelle
Wikipedia hat einen Artikel über Thread-Sicherheit.
Diese Definitionsseite (Sie müssen eine Anzeige überspringen - sorry) definiert sie folgendermaßen:
Ein Thread ist ein Ausführungspfad eines Programms. Ein einzelnes Thread-Programm hat nur einen Thread, sodass dieses Problem nicht auftritt. Praktisch alle GUI-Programme haben mehrere Ausführungspfade und damit Threads - es gibt mindestens zwei, einen zum Verarbeiten der Anzeige der GUI und zum Übergeben von Benutzereingaben und mindestens einen zum tatsächlichen Ausführen der Programmoperationen.
Dies geschieht, damit die Benutzeroberfläche während der Arbeit des Programms weiterhin reagiert, indem lang laufende Prozesse auf Threads außerhalb der Benutzeroberfläche verlagert werden. Diese Threads können einmal erstellt werden und für die gesamte Lebensdauer des Programms vorhanden sein oder bei Bedarf erstellt und nach Abschluss zerstört werden.
Da diese Threads häufig allgemeine Aktionen ausführen müssen - Festplatten-E / A, Ausgabe von Ergebnissen auf dem Bildschirm usw. - müssen diese Teile des Codes so geschrieben werden, dass sie von mehreren Threads aufgerufen werden können, häufig um die selbe Zeit. Dies beinhaltet Dinge wie:
quelle
Thread-sicher bedeutet einfach, dass eine Methode oder Klasseninstanz von mehreren Threads gleichzeitig verwendet werden kann, ohne dass Probleme auftreten.
Betrachten Sie die folgende Methode:
Nun möchten sowohl Thread A als auch Thread B AddOne () ausführen. aber A startet zuerst und liest den Wert von myInt (0) in tmp. Aus irgendeinem Grund beschließt der Scheduler, Thread A anzuhalten und die Ausführung auf Thread B zu verschieben. Thread B liest jetzt auch den Wert von myInt (immer noch 0) in seine eigene Variable tmp. Thread B beendet die gesamte Methode, also ist am Ende myInt = 1. Und 1 wird zurückgegeben. Jetzt ist Thread A wieder an der Reihe. Thread A wird fortgesetzt. Und addiert 1 zu tmp (tmp war 0 für Thread A). Und speichert diesen Wert dann in myInt. myInt ist wieder 1.
In diesem Fall wurde die Methode AddOne zweimal aufgerufen. Da die Methode jedoch nicht threadsicher implementiert wurde, ist der Wert von myInt nicht wie erwartet 2, sondern 1, da der zweite Thread die Variable myInt gelesen hat, bevor der erste Thread beendet wurde Aktualisierung.
Das Erstellen threadsicherer Methoden ist in nicht trivialen Fällen sehr schwierig. Und es gibt einige Techniken. In Java können Sie eine Methode als synchronisiert markieren. Dies bedeutet, dass jeweils nur ein Thread diese Methode ausführen kann. Die anderen Threads warten in der Schlange. Dies macht einen Methoden-Thread sicher, aber wenn in einer Methode viel Arbeit zu erledigen ist, verschwendet dies viel Platz. Eine andere Technik besteht darin, "nur einen kleinen Teil einer Methode als synchronisiert zu markieren".durch Erstellen einer Sperre oder eines Semaphors und Sperren dieses kleinen Teils (normalerweise als kritischer Abschnitt bezeichnet). Es gibt sogar einige Methoden, die als sperrenlos Thread-sicher implementiert sind. Dies bedeutet, dass sie so aufgebaut sind, dass mehrere Threads gleichzeitig durch sie laufen können, ohne jemals Probleme zu verursachen. Dies kann nur bei einer Methode der Fall sein führt einen atomaren Aufruf aus. Atomic Calls sind Anrufe, die nicht unterbrochen werden können und jeweils nur von einem Thread ausgeführt werden können.
quelle
In der realen Welt ist ein Beispiel für den Laien
Angenommen, Sie haben ein Bankkonto bei Internet und Mobile Banking und Ihr Konto hat nur 10 US-Dollar. Sie haben das Überweisungsguthaben mithilfe von Mobile Banking auf ein anderes Konto übertragen und in der Zwischenzeit Online-Einkäufe über dasselbe Bankkonto getätigt. Wenn dieses Bankkonto nicht threadsicher ist, können Sie mit der Bank zwei Transaktionen gleichzeitig ausführen, und die Bank wird bankrott.
Threadsafe bedeutet, dass sich der Status eines Objekts nicht ändert, wenn gleichzeitig mehrere Threads versuchen, auf das Objekt zuzugreifen.
quelle
Weitere Erklärungen finden Sie im Buch "Java Concurrency in Practice":
quelle
Ein Modul ist threadsicher, wenn es garantiert, dass es seine Invarianten angesichts der Verwendung von Multithreads und der gleichzeitigen Verwendung beibehalten kann.
Hier kann ein Modul eine Datenstruktur, eine Klasse, ein Objekt, eine Methode / Prozedur oder eine Funktion sein. Grundsätzlich Umfang Code und zugehörige Daten.
Die Garantie kann möglicherweise auf bestimmte Umgebungen wie eine bestimmte CPU-Architektur beschränkt sein, muss jedoch für diese Umgebungen gelten. Wenn es keine explizite Abgrenzung von Umgebungen gibt, wird normalerweise angenommen, dass für alle Umgebungen gilt, dass der Code kompiliert und ausgeführt werden kann.
Thread-unsichere Module funktionieren möglicherweise bei gleichzeitiger Verwendung mit mehreren Threads ordnungsgemäß. Dies ist jedoch häufig eher auf Glück und Zufall als auf sorgfältiges Design zurückzuführen. Selbst wenn ein Modul für Sie unter nicht beschädigt wird, kann es beim Verschieben in andere Umgebungen beschädigt werden.
Multithreading-Fehler sind oft schwer zu debuggen. Einige von ihnen kommen nur gelegentlich vor, während andere sich aggressiv manifestieren - auch dies kann umgebungsspezifisch sein. Sie können sich als subtil falsche Ergebnisse oder Deadlocks manifestieren. Sie können Datenstrukturen auf unvorhersehbare Weise durcheinander bringen und dazu führen, dass andere scheinbar unmögliche Fehler in anderen entfernten Teilen des Codes auftreten. Es kann sehr anwendungsspezifisch sein, daher ist es schwierig, eine allgemeine Beschreibung zu geben.
quelle
Thread-Sicherheit : Ein Thread-sicheres Programm schützt seine Daten vor Speicherkonsistenzfehlern. In einem Programm mit mehreren Threads verursacht ein threadsicheres Programm keine Nebenwirkungen bei mehreren Lese- / Schreibvorgängen von mehreren Threads für dieselben Objekte. Verschiedene Threads können Objektdaten ohne Konsistenzfehler gemeinsam nutzen und ändern.
Sie können die Thread-Sicherheit mithilfe der erweiterten Parallelitäts-API erreichen. Diese Dokumentation Seite bietet eine gute Programmierkonstrukte Thread - Sicherheit zu erreichen.
Sperrobjekte unterstützen Sperrsprachen, die viele gleichzeitige Anwendungen vereinfachen.
Ausführende definieren eine allgemeine API zum Starten und Verwalten von Threads. Von java.util.concurrent bereitgestellte Executor-Implementierungen bieten eine Thread-Pool-Verwaltung, die für umfangreiche Anwendungen geeignet ist.
Gleichzeitige Sammlungen erleichtern die Verwaltung großer Datensammlungen und können den Synchronisierungsbedarf erheblich reduzieren.
Atomic Variables verfügen über Funktionen, die die Synchronisation minimieren und Speicherkonsistenzfehler vermeiden.
ThreadLocalRandom (in JDK 7) bietet eine effiziente Generierung von Pseudozufallszahlen aus mehreren Threads.
Weitere Programmierkonstrukte finden Sie auch in den Paketen java.util.concurrent und java.util.concurrent.atomic .
quelle
Sie arbeiten eindeutig in einer WinForms-Umgebung. WinForms-Steuerelemente weisen eine Thread-Affinität auf. Dies bedeutet, dass der Thread, in dem sie erstellt werden, der einzige Thread ist, mit dem auf sie zugegriffen und sie aktualisiert werden können. Aus diesem Grund finden Sie auf MSDN und anderswo Beispiele, die zeigen, wie der Rückruf auf den Hauptthread zurückgeführt wird.
Die normale WinForms-Praxis besteht darin, einen einzelnen Thread zu haben, der für alle Ihre UI-Arbeiten vorgesehen ist.
quelle
Ich finde, dass das Konzept von http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 das ist, was ich normalerweise als unsicheres Threading betrachte, wenn eine Methode einen Nebeneffekt wie eine globale Variable hat und darauf beruht.
Ich habe zum Beispiel Code gesehen, der Gleitkommazahlen in Zeichenfolgen formatiert hat. Wenn zwei davon in unterschiedlichen Threads ausgeführt werden, kann der globale Wert von decimalSeparator dauerhaft in 'geändert werden.
quelle
Lesen Sie die folgenden Abschnitte, um die Thread-Sicherheit zu verstehen :
quelle