Haben Sie schon einmal an einem Rennen teilgenommen? Dann wissen Sie bereits, dass manchmal ein Fotofinish erforderlich ist, um den Sieger zu ermitteln! Aber was wäre, wenn zwei Personen gleichzeitig die Ziellinie erreichen würden? Willkommen unter Race Condition.
Haben Sie schon einmal an einem Rennen teilgenommen? Wenn ja, wissen Sie bereits, dass manchmal ein Fotofinish erforderlich ist, um den Sieger zu ermitteln! Aber was wäre, wenn zwei Personen gleichzeitig die Ziellinie erreichen würden? Willkommen unter Race Condition.
Was sind Computer-Threads ?
Um einen Race Condition zu erklären, müssen wir zunächst ein wenig darüber verstehen, wie Computer intern funktionieren. Wenn Sie ein Betriebssystem verwenden, führen Sie verschiedene Aktionen aus, z. B. das Öffnen eines Eingabeaufforderungsfensters, das Öffnen eines Browsers usw. Jede dieser Aktionen führt zu einer Reaktion des Betriebssystems, bei der ein neuer Rechen-/Computer-Thread gestartet wird.
Ein Thread ist ein Rechen-/Computerprozess, der die verschiedenen Schritte (Programmierschritte, die ursprünglich im Quellcodeformat geschrieben und regelmäßig von einem Compiler kompiliert wurden) ausführt/startet, die zur Ausführung der Aufgabe erforderlich sind, die Sie dem Betriebssystem oder der darauf laufenden Software aufgetragen haben.
Unter Linux wird ein solcher Thread eindeutig durch einen PID (Process Identifier) identifiziert. Weitere Informationen zu PIDs unter Linux finden Sie in unseren Artikeln Bash-Automatisierung und Scripting-Grundlagen (Teil 3) und Funktionsweise von Linux-Signalen: SIGINT, SIGTERM und SIGKILL .
Unter Windows wird ein Thread ebenfalls eindeutig durch eine Prozess-ID identifiziert (siehe die PID- Spalte im Windows Task-Manager), obwohl die Implementierung der Prozessverwaltung unter Linux und Windows unterschiedlich ist; unterschiedlicher zugrunde liegender Code, unterschiedliche PID- Interaktionstools usw. und eingeschränkte Kompatibilität. Außerdem darf die Windows-Prozess-ID PID nicht mit der Produkt-ID PID (gleicher Begriff, andere Bedeutung) oder VID (Vendor ID) verwechselt werden . Die beiden letzteren beziehen sich auf die Identifizierung von Geräten und haben nichts mit der Prozessverwaltung zu tun.
Wenn ein Thread gestartet wird, kann er selbst andere Threads starten. Der ursprüngliche Thread wird oft als Haupt- oder übergeordneter Thread bezeichnet. Wenn Sie beispielsweise auf das Symbol Ihres bevorzugten Webbrowsers klicken, wird sofort ein Thread (der Hauptthread) gestartet, und dieser Thread startet sehr schnell mehrere Unterthreads oder untergeordnete Threads und wird so zum übergeordneten Thread.
Sie können sich Threads auch wie Läufer in einem Rennen vorstellen. Denken Sie beispielsweise an einen ausgelasteten Datenbankserver, der viele verschiedene verbundene Clients bedient. Jeder dieser Client-Threads (beachten Sie die Verwendung des Wortes Thread) hat (in vielen Fällen) für sich genommen mindestens einen Thread auf dem Datenbank-Hostserver und/oder in der Datenbanksoftware selbst (d. h. zwei Threads, einer ist beim Betriebssystem angemeldet und einer in der Datenbanksoftware).
Der Datenbankserver versucht, alle diese Threads gleichzeitig zu bedienen (daher auch der Begriff „ gleichzeitige Prozesse “ oder „gleichzeitige Threads “). Wenn die Datenbanksoftware (oder das Betriebssystem usw.) Fehler enthält, kann es früher oder später zu einem Race Condition-Problem kommen.
Was ist ein Race Condition ?
Eine einfache Möglichkeit, dies mit Läufern in einem Rennen zu vergleichen, besteht darin, sich ein Fotofinish vorzustellen, bei dem zwei Läufer tatsächlich gleichzeitig die Ziellinie überqueren. Es ist möglich, wenn auch ziemlich unwahrscheinlich, dass dies bei menschlichen Rennen passiert. Für Computer, die Tausende von Operationen pro Millisekunde verarbeiten, wird es viel wahrscheinlicher.
Stellen Sie sich als weiteres Beispiel einen Staffellauf vor, bei dem die Läufer einen Staffelstab (den auffällig farbigen Stock) von einer Person zur nächsten weitergeben. Stellen Sie sich nun vor, dass einer der Rennteilnehmer einen Fehler macht und es nun zwei Läufer gibt, die meinen, sie sollten den rot gefärbten Staffelstab bekommen.
Ein bedeutendes Ereignis bei einem Staffellauf ist die Stabübergabe, da dies bedeuten kann, dass der vorherige Stabsinhaber mit dem Laufen aufhören kann und es nun am neuen Stabsinhaber liegt, sein Bestes zu geben. Jetzt greifen zwei Läufer nach dem Stab. Es wird eine interessante Situation sein, die man im Fernsehen verfolgen kann (wenn man so etwas mag), aber es ist klar, dass es einige Konsequenzen geben wird.
Im Wesentlichen ist ein Race Condition ein Bug, Fehler oder Defekt im Computersystemcode, der unvorhersehbare Ergebnisse hervorbringt: eine unerwartete Abfolge von Ereignissen. Normalerweise wird er durch zwei Threads verursacht, die in irgendeiner Weise miteinander in Konflikt geraten, wobei mehr als zwei Threads am eigentlichen Konflikt beteiligt sein können und häufig mehr als zwei Threads in der fehlerhaften Software ausgeführt werden.
In unserem Beispiel mit der Menschheit griffen zwei Personen ungefähr zur gleichen Zeit auf ein Objekt zu, und die Beschädigung (ein Computerbegriff, der angibt, dass einige Daten beschädigt waren, wobei sich diese Daten im Speicher, auf der Festplatte oder in der CPU usw. befinden könnten) trat zufällig in dem Moment auf, als zwei Personen (oder zwei Threads in der Computeranalogie) versuchten, den Staffelstab zu ergreifen, und es zu einem Konflikt kam. In Computerbegriffen versuchten zwei Threads, einen Speicherplatz zu beschreiben, der normalerweise nur von einem Thread (einem Runner) beschrieben werden sollte.
Race Conditions können in verschiedenen Bereichen auftreten, beispielsweise in der Elektronik, in Computersoftware und im allgemeinen Leben. Ein Anrufkollision ist beispielsweise ein Begriff aus der Telekommunikation, der die Situation beschreibt, in der ein Kommunikationskanal an beiden Enden gleichzeitig belegt ist. In der Computersoftware – einem der bekanntesten Bereiche von Race Conditions – sind eine Vielzahl von Race Conditions möglich.
Als weiteres Beispiel für einen Race Condition in Computersoftware stellen wir uns zwei Computer-Threads vor, die mit einem bestimmten Speicherplatz arbeiten. Ein Benutzer hat gerade ein Formular übermittelt und die Backend-Software schreibt dieses Formular in den Speicher. Gleichzeitig liest ein anderer Benutzer die Felder dieses Formulars aus demselben Speicherplatz aus. Je nachdem, was passiert, erhält der lesende Benutzer möglicherweise ein teilweise falsches Formular mit teilweise aktualisierten Informationen.
Race Conditions verhindern: Thread-Sicherheit
In der IT-Branche wurde viel über Race Conditions diskutiert. Je nachdem, welche Programmiersprache Sie verwenden, gibt es möglicherweise umfangreiche oder nur wenige Bestimmungen zum Umgang mit Race Conditions. Ein häufig verwendeter Begriff ist Threadsicherheit oder threadsichere Anwendung oder Programmiersprache [Konstrukt]. Solche Begriffe werden verwendet, um anzugeben, ob ein Codestück oder eine Software als Ganzes threadsicher ist , d. h. so geschrieben ist, dass Race Conditions vermieden oder sogar verhindert werden.
Wenn Software als threadsicher gilt , wird angenommen, dass sie frei von der Möglichkeit von Race Conditions ist. In vielen Fällen ist „ als“ threadsicher gelten das Beste, was Entwickler liefern können, und das gilt umso mehr, wenn viele Threads und Interaktionen möglich sind. Die Komplexität vieler Threads, die mit vielen Ressourcen arbeiten, kann leicht zu einer Myriade von Code-Handling und einer noch größeren Myriade möglicher Race Conditions führen.
Um Race Conditions zu vermeiden, können verschiedene Programmierkonstrukte verwendet werden. Beispielsweise Semaphore und Mutexe. Die Komplexität der Verwendung solcher Konstrukte hängt von der verwendeten Programmiersprache und ihrer nativen Unterstützung für eine verbesserte Thread-Behandlung ab. In C++ kann man sich beispielsweise die Klasse std::mutex ansehen , um eine Mutex-Sperre (d. h. gegenseitig exklusive Sperre) zu implementieren. In Bash findet man eine solche Konstrukte jedoch nicht nativ gacha.
Wenn man einen Schritt weitergeht, kann man auch überlegen, welche bestimmten Konstrukte, Funktionen oder sogar ausführbaren Dateien und Bibliotheken bereits threadsicher sind, und dann diese Konstrukte, Funktionen, ausführbaren Dateien und Bibliotheken als Grundlage für die Erstellung einer neuen Konstrukte, Funktion, ausführbaren Datei, Bibliothek oder eines vollständigen Softwarepakets verwenden.
Selbst die Implementierung grundlegender Konstrukte zur Thread-Sicherheit kann eine komplexe Angelegenheit sein. Denken Sie beispielsweise an die Schwierigkeit, ein Semaphor in Bash zu implementieren .
Einpacken
In diesem Artikel haben wir uns mit Computer-Threads und Race Conditions beschäftigt. Wir haben uns Analogien zu Wettrennen und Staffelläufen im menschlichen Leben angesehen, um einige grundlegende Race Conditions zu untersuchen, die in Computern auftreten können. Schließlich haben wir uns mit Thread-Sicherheit, den verschiedenen Implementierungen der Race Condition-Behandlung in Computer-Programmiersprachen und damit beschäftigt, wie wir Race Conditions verhindern können.
Wenn Ihnen dieser Artikel gefallen hat, schauen Sie sich den Artikel „So funktionieren Logikgatter: ODER, UND, XOR, NOR, NAND, XNOR und NICHT“ an .