Rennbedingung - Race condition

Racebedingung in einer Logikschaltung. Hier repräsentieren t 1 und ∆ t 2 die Ausbreitungsverzögerungen der Logikelemente. Wenn sich der Eingangswert A von niedrig nach hoch ändert, gibt die Schaltung eine kurze Spitze der Dauer (∆ t 1 + ∆ t 2 ) – t 2 = ∆ t 1 aus .

Eine Race-Condition oder Race-Hazard ist der Zustand einer Elektronik , Software oder eines anderen Systems, bei dem das wesentliche Verhalten des Systems von der Abfolge oder dem Zeitpunkt anderer unkontrollierbarer Ereignisse abhängt. Es wird zu einem Fehler, wenn eines oder mehrere der möglichen Verhaltensweisen unerwünscht sind.

Der Begriff Race Condition war bereits 1954 in Gebrauch, beispielsweise in David A. Huffmans Doktorarbeit „Die Synthese sequentieller Schaltkreise“.

Race-Bedingungen können insbesondere in Logikschaltungen , Multithread- oder verteilten Softwareprogrammen auftreten.

In der Elektronik

Ein typisches Beispiel für eine Wettlaufbedingung kann auftreten, wenn ein Logikgatter Signale kombiniert, die von derselben Quelle entlang unterschiedlicher Pfade gewandert sind. Die Eingänge zum Gate können sich als Reaktion auf eine Änderung des Quellsignals zu leicht unterschiedlichen Zeiten ändern. Der Ausgang kann für einen kurzen Zeitraum in einen unerwünschten Zustand wechseln, bevor er wieder in den Entwurfszustand zurückkehrt. Bestimmte Systeme können solche Störimpulse tolerieren, aber wenn dieser Ausgang als Taktsignal für weitere Systeme fungiert, die beispielsweise Speicher enthalten, kann das System schnell von seinem entworfenen Verhalten abweichen (tatsächlich wird der temporäre Störimpuls zu einem permanenten Störimpuls).

Betrachten Sie zum Beispiel ein UND-Gatter mit zwei Eingängen, das mit der folgenden Logik gespeist wird:

Ein logisches Signal an einem Eingang und deren Negation (die ¬ ist eine Boolesche Negation ), an einem anderen Eingang in der Theorie nicht Ausgang ein wahrer Wert: Wenn jedoch in dem Wert ändert , länger dauert den zweiten Eingang als die ersten fortzupflanzen bei einem Wechsel von false auf true folgt eine kurze Zeitspanne, in der beide Eingänge wahr sind und somit auch der Ausgang des Gatters wahr ist.

Kritische und unkritische Formen

Eine kritische Race-Bedingung tritt auf, wenn die Reihenfolge, in der interne Variablen geändert werden, den endgültigen Zustand bestimmt, in dem die Zustandsmaschine enden wird.

Eine unkritische Race-Bedingung tritt auf, wenn die Reihenfolge, in der interne Variablen geändert werden, nicht den endgültigen Zustand bestimmt, in dem die Zustandsmaschine enden wird.

Statische, dynamische und essentielle Formen

Eine statische Race Condition tritt auf, wenn ein Signal und sein Komplement kombiniert werden.

Eine dynamische Racebedingung tritt auf, wenn sie zu mehreren Übergängen führt, obwohl nur einer beabsichtigt ist. Sie sind auf die Interaktion zwischen den Toren zurückzuführen. Es kann eliminiert werden, indem nicht mehr als zwei Gating-Ebenen verwendet werden.

Eine wesentliche Wettlaufbedingung tritt auf, wenn eine Eingabe zwei Übergänge in weniger als der gesamten Feedback-Ausbreitungszeit aufweist. Manchmal werden sie unter Verwendung von induktiven Verzögerungsleitungselementen ausgehärtet, um die Zeitdauer eines Eingangssignals effektiv zu verlängern.

Problemumgehungen

Designtechniken wie Karnaugh-Maps ermutigen Designer, Racebedingungen zu erkennen und zu beseitigen, bevor sie Probleme verursachen. Oft kann logische Redundanz hinzugefügt werden, um einige Arten von Rassen zu eliminieren.

Zusätzlich zu diesen Problemen können einige Logikelemente in metastabile Zustände eintreten , was weitere Probleme für Schaltungsdesigner schafft.

In der Software

Eine Race-Condition tritt in Software auf, wenn ein Computerprogramm, um richtig zu funktionieren, von der Reihenfolge oder dem Timing der Prozesse oder Threads des Programms abhängt . Kritische Racebedingungen führen zu ungültiger Ausführung und zu Softwarefehlern . Kritische Race-Bedingungen treten häufig auf, wenn die Prozesse oder Threads von einem gemeinsamen Status abhängen. Operationen auf gemeinsam genutzten Zuständen werden in kritischen Abschnitten durchgeführt , die sich gegenseitig ausschließen müssen . Die Nichtbeachtung dieser Regel kann den gemeinsamen Status beschädigen.

Ein Data Race ist eine Art von Race Condition. Data Races sind wichtige Bestandteile verschiedener formaler Speichermodelle . Das in den C11- und C++11- Standards definierte Speichermodell legt fest, dass ein C- oder C++-Programm, das ein Data Race enthält, undefiniertes Verhalten hat .

Eine Racebedingung kann schwer zu reproduzieren und zu debuggen sein, da das Endergebnis nicht deterministisch ist und vom relativen Timing zwischen störenden Threads abhängt. Probleme dieser Art können daher verschwinden, wenn im Debug-Modus ausgeführt, zusätzliche Protokollierung hinzugefügt oder ein Debugger angehängt wird. Ein Fehler, der bei Debugging-Versuchen so verschwindet, wird oft als „ Heisenbug “ bezeichnet. Daher ist es besser, Race-Conditions durch sorgfältiges Softwaredesign zu vermeiden.

Beispiel

Angenommen, zwei Threads inkrementieren jeweils den Wert einer globalen Integer-Variablen um 1. Idealerweise würde die folgende Abfolge von Operationen ablaufen:

Gewinde 1 Gewinde 2 Integer Wert
0
Wert lesen 0
Wert steigern 0
Schreib zurück 1
Wert lesen 1
Wert steigern 1
Schreib zurück 2

Im oben gezeigten Fall ist der Endwert erwartungsgemäß 2. Wenn die beiden Threads jedoch gleichzeitig ohne Sperren oder Synchronisierung ausgeführt werden, kann das Ergebnis der Operation falsch sein. Die folgende alternative Abfolge von Operationen veranschaulicht dieses Szenario:

Gewinde 1 Gewinde 2 Integer Wert
0
Wert lesen 0
Wert lesen 0
Wert steigern 0
Wert steigern 0
Schreib zurück 1
Schreib zurück 1

In diesem Fall ist der Endwert 1 statt des erwarteten Ergebnisses 2. Dies liegt daran, dass sich hier die Inkrementierungsoperationen nicht gegenseitig ausschließen. Sich gegenseitig ausschließende Operationen sind solche, die nicht unterbrochen werden können, während auf eine Ressource wie beispielsweise eine Speicherstelle zugegriffen wird.

Datenrennen

Nicht alle betrachten Datenrennen als Teilmenge von Wettlaufbedingungen. Die genaue Definition von Data Race ist spezifisch für das verwendete formale Parallelitätsmodell, bezieht sich jedoch typischerweise auf eine Situation, in der eine Speicheroperation in einem Thread möglicherweise versuchen könnte, auf eine Speicherstelle zuzugreifen, während gleichzeitig eine Speicheroperation in einem anderen Thread ausgeführt wird Schreiben in diesen Speicherort, in einem Kontext, in dem dies gefährlich ist. Dies impliziert, dass sich ein Datenrennen von einer Wettlaufbedingung unterscheidet, da es auch in einem Programm ohne Datenrennen möglich ist, aufgrund des Timings einen Nichtdeterminismus zu haben, zum Beispiel in einem Programm, in dem alle Speicherzugriffe nur atomare Operationen verwenden .

Dies kann gefährlich sein, da auf vielen Plattformen, wenn zwei Threads gleichzeitig in einen Speicherort schreiben, es möglich sein kann, dass der Speicherort einen Wert enthält, der eine willkürliche und bedeutungslose Kombination der Bits ist, die die Werte darstellen, die jeder Thread versuchte zu schreiben; dies könnte zu einer Speicherbeschädigung führen, wenn der resultierende Wert ein Wert ist, den keiner der Threads versucht hat zu schreiben (manchmal wird dies als " zerrissenes Schreiben " bezeichnet). Wenn ein Thread von einem Speicherort liest, während ein anderer Thread darauf schreibt, kann es ähnlich sein, dass der Lesevorgang einen Wert zurückgibt, der eine willkürliche und bedeutungslose Kombination der Bits ist, die den Wert darstellen, den der Speicherort vor dem Schreiben hielt. und der Bits, die den geschriebenen Wert darstellen.

Auf vielen Plattformen werden spezielle Speicheroperationen für den gleichzeitigen Zugriff bereitgestellt; in solchen Fällen ist normalerweise der gleichzeitige Zugriff unter Verwendung dieser speziellen Operationen sicher, aber der gleichzeitige Zugriff unter Verwendung anderer Speicheroperationen ist gefährlich. Manchmal werden solche Spezialoperationen (die für den gleichzeitigen Zugriff sicher sind) als atomare oder Synchronisationsoperationen bezeichnet , während die gewöhnlichen Operationen (die für den gleichzeitigen Zugriff unsicher sind) als Datenoperationen bezeichnet werden. Dies ist wahrscheinlich der Grund, warum der Begriff Data Race lautet ; auf vielen Plattformen, wo eine Race-Bedingung besteht, die nur Synchronisationsoperationen umfasst , kann ein solches Race nicht deterministisch, aber ansonsten sicher sein; Ein Datenwettlauf kann jedoch zu Speicherbeschädigungen oder undefiniertem Verhalten führen.

Beispieldefinitionen von Data Races in bestimmten Parallelitätsmodellen

Die genaue Definition von Data Race unterscheidet sich zwischen den formalen Parallelitätsmodellen. Dies ist wichtig, weil gleichzeitiges Verhalten oft nicht intuitiv ist und daher manchmal formale Argumentation angewendet wird.

Der C++-Standard im Entwurf N4296 (2014-11-19) definiert Data Race wie folgt in Abschnitt 1.10.23 (Seite 14)

Zwei Aktionen sind potenziell gleichzeitig, wenn

  • sie werden von verschiedenen Threads ausgeführt, oder
  • sie sind nicht sequenziert, und mindestens einer wird von einem Signalhandler ausgeführt.

Die Ausführung eines Programms enthält ein Data Race, wenn es zwei potenziell gleichzeitige widersprüchliche Aktionen enthält, von denen mindestens eine nicht atomar ist und keine vor der anderen stattfindet, mit Ausnahme des unten beschriebenen Sonderfalls für Signalhandler [ausgelassen]. Ein solches Datenrennen führt zu undefiniertem Verhalten.

Die Teile dieser Definition, die sich auf Signalhandler beziehen, sind für C++ idiosynkratisch und nicht typisch für Definitionen von Data Race .

Das Papier Detecting Data Races on Weak Memory Systems bietet eine andere Definition:

„zwei Speicheroperationen Konflikt , wenn sie Zugriff auf die gleiche Position und mindestens einer von ihnen ist ein Schreibvorgang ...“ Zwei Speicheroperationen, x und y, in einer sequentiell konsistenten Ausführung bildet eine Rasse <x, y>, genau dann , wenn x und y-Konflikt, und sie sind nicht nach der hb1-Beziehung der Ausführung geordnet. Das Rennen <x, y>, ist ein Datum Rennen iff mindestens eine von X oder Y eine Datenoperation.

Hier haben wir zwei Speicheroperationen, die auf denselben Speicherort zugreifen, von denen eine ein Schreiben ist.

Die hb1-Relation wird an anderer Stelle in der Abhandlung definiert und ist ein Beispiel für eine typische „ passiert-before “ -Relation ; Wenn wir intuitiv beweisen können, dass wir uns in einer Situation befinden, in der eine Speicheroperation X garantiert vollständig ausgeführt wird, bevor eine andere Speicheroperation Y beginnt, dann sagen wir, dass "X passiert - vor Y". Wenn weder "X passiert-vor Y" noch "Y passiert-before X" ist, dann sagen wir, dass X und Y "nicht nach der hb1-Relation" geordnet sind. So kann die Klausel "...und sie sind nicht nach der hb1-Beziehung der Ausführung geordnet" intuitiv mit "...und X und Y sind potenziell gleichzeitig" übersetzt werden.

Das Papier betrachtet nur solche Situationen als gefährlich, in denen mindestens eine der Speicheroperationen eine "Datenoperation" ist; in anderen Teilen dieses Papiers definiert das Papier auch eine Klasse von " Synchronisationsoperationen ", die im Gegensatz zu "Datenoperationen" für eine potenziell gleichzeitige Verwendung sicher sind.

Die Java Language Specification bietet eine andere Definition:

Zwei Zugriffe (Lese- oder Schreibzugriffe) auf dieselbe Variable werden als widersprüchlich bezeichnet, wenn mindestens einer der Zugriffe ein Schreibzugriff ist...Wenn ein Programm zwei widersprüchliche Zugriffe (§17.4.1) enthält, die nicht nach a geordnet sind geschieht-before-Beziehung, es wird gesagt, dass sie ein Datenrennen enthält ... ein Datenrennen kann kein falsches Verhalten verursachen, wie z. B. die Rückgabe der falschen Länge für ein Array.

Ein entscheidender Unterschied zwischen dem C++-Ansatz und dem Java-Ansatz besteht darin, dass in C++ ein Data Race undefiniertes Verhalten ist, während ein Data Race in Java lediglich "Inter-Thread-Aktionen" betrifft. Dies bedeutet, dass in C++ der Versuch, ein Programm mit einem Datenrennen auszuführen, abstürzen oder ein unsicheres oder bizarres Verhalten zeigen kann (während es sich immer noch an die Spezifikation hält), während in Java der Versuch, ein Programm mit einem Datenrennen auszuführen, unerwünschtes Parallelitätsverhalten, ist aber ansonsten (vorausgesetzt, dass die Implementierung der Spezifikation entspricht) sicher.

SC für DRF

Ein wichtiger Aspekt von Data Races besteht darin, dass in einigen Kontexten ein Programm, das frei von Data Races ist, garantiert sequenziell konsistent ausgeführt wird, was das Nachdenken über das gleichzeitige Verhalten des Programms erheblich erleichtert. Formale Speichermodelle, die eine solche Garantie bieten, sollen eine "SC for DRF"-Eigenschaft (Sequential Consistency for Data Race Freedom) aufweisen. Dieser Ansatz soll in letzter Zeit einen Konsens erreicht haben (vermutlich im Vergleich zu Ansätzen, die in allen Fällen sequentielle Konsistenz garantieren oder überhaupt nicht garantieren).

In Java wird diese Garantie beispielsweise direkt angegeben:

Ein Programm ist genau dann korrekt synchronisiert, wenn alle sequenziell konsistenten Ausführungen frei von Data Races sind.

Wenn ein Programm korrekt synchronisiert ist, erscheinen alle Ausführungen des Programms sequenziell konsistent (§17.4.3).

Dies ist eine extrem starke Garantie für Programmierer. Programmierer müssen nicht über Neuordnungen nachdenken, um festzustellen, dass ihr Code Datenrennen enthält. Daher müssen sie nicht über Neuordnungen nachdenken, wenn sie feststellen, ob ihr Code korrekt synchronisiert ist. Sobald festgestellt wurde, dass der Code korrekt synchronisiert ist, muss sich der Programmierer keine Sorgen machen, dass Neuordnungen seinen oder ihren Code beeinflussen.

Ein Programm muss korrekt synchronisiert werden, um kontraintuitive Verhaltensweisen zu vermeiden, die bei der Neuordnung von Code beobachtet werden können. Die Verwendung einer korrekten Synchronisation stellt nicht sicher, dass das Gesamtverhalten eines Programms korrekt ist. Seine Verwendung erlaubt es einem Programmierer jedoch, auf einfache Weise über das mögliche Verhalten eines Programms nachzudenken; das Verhalten eines korrekt synchronisierten Programms ist viel weniger abhängig von möglichen Neuordnungen. Ohne korrekte Synchronisation sind sehr seltsame, verwirrende und kontraintuitive Verhaltensweisen möglich.

Im Gegensatz dazu erfordert ein Entwurf einer C++-Spezifikation nicht direkt einen SC für die DRF-Eigenschaft, sondern stellt lediglich fest, dass es ein Theorem gibt, das dies bereitstellt:

[Anmerkung: Es kann gezeigt werden, dass Programme, die Mutexes und memory_order_seq_cst-Operationen korrekt verwenden, um alle Datenrennen zu verhindern und keine anderen Synchronisationsoperationen verwenden, sich so verhalten, als ob die von ihren konstituierenden Threads ausgeführten Operationen einfach verschachtelt wären, wobei jede Wertberechnung eines Objekts übernommen wird von der letzten Nebenwirkung auf dieses Objekt in dieser Verschachtelung. Dies wird normalerweise als „sequentielle Konsistenz“ bezeichnet. Dies gilt jedoch nur für Data-Race-freie Programme, und Data-Race-freie Programme können die meisten Programmtransformationen, die die Semantik von Single-Thread-Programmen nicht ändern, nicht beobachten. Tatsächlich sind die meisten Singlethread-Programmtransformationen weiterhin erlaubt, da jedes Programm, das sich dadurch anders verhält, eine undefinierte Operation ausführen muss.— Endnote

Beachten Sie, dass der Spezifikationsentwurf von C++ die Möglichkeit von Programmen zulässt, die gültig sind, aber Synchronisationsoperationen mit einer anderen memory_order als memory_order_seq_cst verwenden. Mit anderen Worten, in C++ sind einige korrekte Programme nicht sequenziell konsistent. Es wird angenommen, dass dieser Ansatz C++-Programmierern die Freiheit gibt, eine schnellere Programmausführung zu wählen, auf Kosten der Einfachheit, über ihr Programm nachzudenken.

Es gibt verschiedene Theoreme, die oft in Form von Speichermodellen bereitgestellt werden, die SC für DRF-Garantien in verschiedenen Kontexten bereitstellen. Die Prämissen dieser Theoreme erlegen typischerweise sowohl dem Speichermodell (und damit der Implementierung) als auch dem Programmierer Beschränkungen auf; das heißt, typischerweise gibt es Programme, die die Prämissen des Theorems nicht erfüllen und deren sequenziell konsistente Ausführung nicht garantiert werden kann.

Das DRF1-Speichermodell bietet SC für DRF und ermöglicht die Optimierungen des WO (Weak Ordering), RCsc ( Release Consistency mit sequentiell konsistenten Spezialoperationen), VAX-Speichermodell und Data-Race-free-0-Speichermodellen. Das PLpc-Speichermodell stellt SC für DRF bereit und ermöglicht die Optimierungen der Modelle TSO ( Total Store Order ), PSO, PC ( Prozessorkonsistenz ) und RCpc ( Release Consistency with Processor Consistency Special Operations). DRFrlx liefert eine Skizze eines SC für das DRF-Theorem in Gegenwart entspannter Atome.

Computersicherheit

Viele Software-Race-Bedingungen haben Auswirkungen auf die Computersicherheit . Eine Race Condition ermöglicht es einem Angreifer mit Zugriff auf eine gemeinsam genutzte Ressource, Fehlfunktionen anderer Akteure, die diese Ressource nutzen, zu verursachen, was zu Auswirkungen wie Denial-of-Service und Privilegieneskalation führt .

Eine spezielle Art von Race Condition beinhaltet die Prüfung auf ein Prädikat (z. B. zur Authentifizierung ) und dann die Reaktion auf das Prädikat, während sich der Zustand zwischen dem Zeitpunkt der Prüfung und dem Zeitpunkt der Verwendung ändern kann . Wenn diese Art von Fehler in sicherheitskritischem Code vorhanden ist, entsteht eine Sicherheitslücke, die als Time-of-Check-to-Time-of-Use- Bug ( TOCTTOU ) bezeichnet wird.

Race-Bedingungen werden auch absichtlich verwendet, um Hardware-Zufallszahlengeneratoren und physikalisch nicht klonbare Funktionen zu erstellen . PUFs können erstellt werden, indem Schaltungstopologien mit identischen Pfaden zu einem Knoten entworfen werden und sich auf Herstellungsvariationen verlassen, um zufällig zu bestimmen, welche Pfade zuerst abgeschlossen werden. Durch Messen der spezifischen Ergebnisse der Rennbedingungen jeder hergestellten Rennstrecke kann ein Profil für jede Rennstrecke gesammelt und geheim gehalten werden, um später die Identität einer Rennstrecke zu überprüfen.

Dateisysteme

Zwei oder mehr Programme können bei ihren Versuchen, ein Dateisystem zu ändern oder auf ein Dateisystem zuzugreifen, kollidieren, was zu Datenkorruption oder Privilegieneskalation führen kann. Das Sperren von Dateien bietet eine häufig verwendete Lösung. Eine umständlichere Lösung besteht darin, das System so zu organisieren, dass ein einzelner Prozess (der einen Daemon oder dergleichen ausführt ) exklusiven Zugriff auf die Datei hat und alle anderen Prozesse, die auf die Daten in dieser Datei zugreifen müssen, dies nur über die Interprozesskommunikation tun mit diesem einen Prozess. Dies erfordert eine Synchronisation auf Prozessebene.

Eine andere Form von Race Condition existiert in Dateisystemen, in denen sich nicht verwandte Programme gegenseitig beeinflussen können, indem sie plötzlich verfügbare Ressourcen wie Plattenplatz, Speicherplatz oder Prozessorzyklen verbrauchen. Software, die nicht sorgfältig entwickelt wurde, um diese Race-Situation zu antizipieren und zu handhaben, kann dann unvorhersehbar werden. Ein solches Risiko kann in einem System, das sehr zuverlässig erscheint, lange Zeit übersehen werden. Aber schließlich können sich genügend Daten ansammeln oder es kann genügend andere Software hinzugefügt werden, um viele Teile eines Systems kritisch zu destabilisieren. Ein Beispiel dafür war der Beinaheverlust des Mars Rover "Spirit" kurz nach der Landung. Eine Lösung besteht darin, dass Software alle benötigten Ressourcen anfordert und reserviert, bevor sie mit einer Aufgabe beginnt. Wenn diese Anforderung fehlschlägt, wird die Aufgabe verschoben, wodurch die vielen Punkte vermieden werden, an denen ein Fehler hätte auftreten können. Alternativ kann jeder dieser Punkte mit einer Fehlerbehandlung ausgestattet werden oder der Erfolg der gesamten Aufgabe kann im Nachhinein überprüft werden, bevor es weitergeht. Ein gängigerer Ansatz besteht darin, einfach zu überprüfen, ob genügend Systemressourcen verfügbar sind, bevor eine Aufgabe gestartet wird. Dies ist jedoch möglicherweise nicht ausreichend, da in komplexen Systemen die Aktionen anderer laufender Programme unvorhersehbar sein können.

Vernetzung

Betrachten Sie beim Networking ein verteiltes Chat-Netzwerk wie IRC , bei dem ein Benutzer, der einen Channel startet, automatisch Channel-Operator-Privilegien erhält. Wenn zwei Benutzer auf verschiedenen Servern an verschiedenen Enden desselben Netzwerks versuchen, den gleichnamigen Kanal gleichzeitig zu starten, gewährt der jeweilige Server jedes Benutzers jedem Benutzer Kanalbetreiber-Privilegien, da noch keiner der Server die Signal eines anderen Servers, dass er diesen Kanal zugewiesen hat. (Dieses Problem wurde durch verschiedene IRC-Serverimplementierungen weitgehend gelöst .)

In diesem Fall einer Race Condition umfasst das Konzept der „ Shared Resource “ den Zustand des Netzwerks (welche Kanäle existieren, sowie welche Benutzer sie gestartet haben und somit welche Privilegien haben), den jeder Server frei ändern kann, solange es signalisiert den anderen Servern im Netzwerk die Änderungen, damit sie ihre Vorstellung vom Zustand des Netzwerks aktualisieren können. Die Latenz im Netzwerk ermöglicht jedoch die beschriebene Art von Race Condition. In diesem Fall würde es bedeuten, das verteilte Netzwerk in ein zentralisiertes Netzwerk umzuwandeln (zumindest für diesen einen Teil) des Netzbetriebs).

Race-Bedingungen können auch vorliegen, wenn ein Computerprogramm mit nicht-blockierenden Sockets geschrieben wird. In diesem Fall kann die Leistung des Programms von der Geschwindigkeit der Netzwerkverbindung abhängen.

Lebenskritische Systeme

Softwarefehler in lebenswichtigen Systemen können katastrophal sein. Zu den Fehlern des Therac-25- Strahlentherapiegeräts gehörten die Rennbedingungen , die zum Tod von mindestens drei Patienten und zu mehreren Verletzungen führten.

Ein weiteres Beispiel ist das Energiemanagementsystem zur Verfügung gestellt von GE Energy und wurde von Ohio -basierte Firstenergy Corp (unter anderem Kraftanlagen). Im Alarmsubsystem lag eine Wettlaufbedingung vor; Wenn drei durchhängende Stromleitungen gleichzeitig ausgelöst wurden, verhinderte die Bedingung, dass Alarme an die Überwachungstechniker ausgegeben wurden, wodurch deren Bewusstsein für das Problem verzögert wurde. Dieser Softwarefehler führte schließlich zum nordamerikanischen Blackout von 2003 . GE Energy entwickelte später einen Software-Patch, um den zuvor unentdeckten Fehler zu beheben.

Werkzeuge

Es gibt viele Softwaretools, um Race-Bedingungen in Software zu erkennen. Sie können grob in zwei Gruppen eingeteilt werden: statische Analysewerkzeuge und dynamische Analysewerkzeuge .

Thread Safety Analysis ist ein statisches Analysetool für annotationsbasierte intraprozedurale statische Analyse, das ursprünglich als Zweig von gcc implementiert und jetzt in Clang neu implementiert wurde und PThreads unterstützt.

Dynamische Analysetools umfassen:

  • Intel Inspector , ein Tool zum Überprüfen und Debuggen von Speicher und Threads, um die Zuverlässigkeit, Sicherheit und Genauigkeit von C/C++- und Fortran-Anwendungen zu erhöhen; Intel Advisor , ein Sampling-basiertes, SIMD-Vektorisierungsoptimierungs- und Shared-Memory-Threading-Hilfstool für C-, C++-, C#- und Fortran-Softwareentwickler und -architekten;
  • ThreadSanitizer, der binäre ( Valgrind- basiert) oder Quell-, LLVM- basierte Instrumentierung verwendet und PThreads unterstützt; und Helgrind, ein Valgrind- Tool zum Erkennen von Synchronisationsfehlern in C-, C++- und Fortran-Programmen, die die POSIX-pthreads-Threading-Primitive verwenden.
  • Data Race Detector wurde entwickelt, um Data Races in der Programmiersprache Go zu finden.

Es gibt mehrere Benchmarks, die entwickelt wurden, um die Wirksamkeit von Tools zur Erkennung von Datenrassen zu bewerten

  • DataRaceBench ist eine Benchmark-Suite, die entwickelt wurde, um Tools zur Erkennung von Data Races systematisch und quantitativ zu bewerten, die in OpenMP geschriebene Multithread-Anwendungen analysieren .

In anderen Bereichen

Die Neurowissenschaft zeigt, dass Rassebedingungen auch im Gehirn von Säugetieren (Ratten) auftreten können.

Bei der britischen Eisenbahnsignalisierung würde bei der Durchführung von Regel 55 eine Wettlaufbedingung entstehen . Nach dieser Regel ging der Lokfeuerwehrmann zum Stellwerk, wenn ein Zug auf einer Fahrbahn durch ein Signal angehalten wurde, um den Stellwerkswärter an die Anwesenheit des Zuges zu erinnern. In mindestens einem Fall ereignete sich 1934 in Winwick ein Unfall, weil der Stellwerkswärter einen anderen Zug akzeptierte, bevor der Feuerwehrmann eintraf. Die moderne Signaltechnik beseitigt die Rennbedingung, indem sie es dem Fahrer ermöglicht, das Stellwerk sofort per Funk zu kontaktieren.

Siehe auch

Verweise

Externe Links