1328 Stimmen

Was ist eine Rennbedingung?

Beim Schreiben von Multithreading-Anwendungen ist eines der häufigsten Probleme die Race Condition.

Meine Fragen an die Gemeinschaft lauten:

  • Was ist die Rennbedingung?
  • Wie kann man sie erkennen?
  • Wie gehen Sie mit ihnen um?
  • Und schließlich: Wie kann man verhindern, dass sie auftreten?

10 Stimmen

Ich möchte darauf hinweisen, dass - ohne Angabe der Sprache - die meisten Teile dieser Frage nicht richtig beantwortet werden können, da die Definition, die Folgen und die Instrumente zu ihrer Verhinderung in den verschiedenen Sprachen unterschiedlich sein können.

0 Stimmen

@MikeMB. Einverstanden, außer bei der Analyse der Ausführung von Bytecode, wie sie von Race Catcher durchgeführt wird (siehe diesen Thread stackoverflow.com/a/29361427/1363844 ) können wir all die etwa 62 Sprachen ansprechen, die sich zu Bytecode kompilieren lassen (siehe de.wikipedia.org/wiki/Liste_der_JVM_Sprachen )

1664voto

Lehane Punkte 45250

Eine Race Condition tritt auf, wenn zwei oder mehr Threads auf gemeinsame Daten zugreifen können und versuchen, sie gleichzeitig zu ändern. Da der Thread-Planungsalgorithmus jederzeit zwischen den Threads wechseln kann, wissen Sie nicht, in welcher Reihenfolge die Threads versuchen werden, auf die gemeinsamen Daten zuzugreifen. Daher hängt das Ergebnis der Datenänderung vom Thread-Scheduling-Algorithmus ab, d. h. beide Threads "rennen" um den Zugriff auf die Daten bzw. deren Änderung.

Probleme treten häufig auf, wenn ein Thread ein "check-then-act" durchführt (z.B. "check", ob der Wert X ist, dann "act", um etwas zu tun, was davon abhängt, dass der Wert X ist) und ein anderer Thread etwas mit dem Wert zwischen dem "check" und dem "act" macht. Z.B.:

if (x == 5) // The "Check"
{
   y = x * 2; // The "Act"

   // If another thread changed x in between "if (x == 5)" and "y = x * 2" above,
   // y will not be equal to 10.
}

Der Punkt ist, dass y 10 sein könnte, oder irgendetwas, je nachdem, ob ein anderer Thread x zwischen der Prüfung und der Handlung verändert hat. Sie haben keine Möglichkeit, das zu wissen.

Um das Auftreten von Wettlaufsituationen zu verhindern, würden Sie normalerweise eine Sperre um die gemeinsam genutzten Daten legen, um sicherzustellen, dass nur ein Thread gleichzeitig auf die Daten zugreifen kann. Dies würde in etwa so aussehen:

// Obtain lock for x
if (x == 5)
{
   y = x * 2; // Now, nothing can change x until the lock is released. 
              // Therefore y = 10
}
// release lock for x

177 Stimmen

Was macht der andere Thread, wenn er auf die Sperre stößt? Wartet er? Fehler?

241 Stimmen

Ja, der andere Thread muss warten, bis die Sperre freigegeben wird, bevor er fortfahren kann. Daher ist es sehr wichtig, dass die Sperre vom haltenden Thread freigegeben wird, wenn er damit fertig ist. Wenn er sie nie freigibt, wird der andere Thread unendlich lange warten.

3 Stimmen

@Ian In einem Multithreading-System wird es immer Zeiten geben, in denen Ressourcen gemeinsam genutzt werden müssen. Zu sagen, dass ein Ansatz schlecht ist, ohne eine Alternative zu nennen, ist einfach nicht produktiv. Ich bin immer auf der Suche nach Verbesserungsmöglichkeiten, und wenn es eine Alternative gibt, werde ich sie gerne untersuchen und die Vor- und Nachteile abwägen.

259voto

privatehuff Punkte 2699

Eine "Race Condition" liegt vor, wenn Multithreading- (oder anderweitig paralleler) Code, der auf eine gemeinsam genutzte Ressource zugreift, unerwartete Ergebnisse hervorrufen könnte.

Nehmen Sie dieses Beispiel:

for ( int i = 0; i < 10000000; i++ )
{
   x = x + 1; 
}

Wenn Sie 5 Threads hätten, die diesen Code gleichzeitig ausführen, würde der Wert von x NICHT 50.000.000 betragen. Er würde vielmehr bei jedem Durchlauf variieren.

Das liegt daran, dass jeder Thread, um den Wert von x zu erhöhen, Folgendes tun muss: (natürlich vereinfacht)

Retrieve the value of x
Add 1 to this value
Store this value to x

Jeder Thread kann sich jederzeit in einem beliebigen Schritt dieses Prozesses befinden, und sie können sich gegenseitig beeinflussen, wenn eine gemeinsame Ressource betroffen ist. Der Zustand von x kann von einem anderen Thread in der Zeit zwischen dem Lesen und dem Zurückschreiben von x geändert werden.

Angenommen, ein Thread ruft den Wert von x ab, hat ihn aber noch nicht gespeichert. Ein anderer Thread kann auch den dieselbe Wert von x (weil ihn noch kein Thread geändert hat) und dann würden beide den dieselbe Wert (x+1) zurück in x!

Beispiel:

Thread 1: reads x, value is 7
Thread 1: add 1 to x, value is now 8
Thread 2: reads x, **value is 7**
Thread 1: stores 8 in x
Thread 2: adds 1 to x, value is now 8
Thread 2: **stores 8 in x**

Race-Bedingungen können vermieden werden, indem man eine Art von Verriegelung Mechanismus vor dem Code, der auf die gemeinsame Ressource zugreift:

for ( int i = 0; i < 10000000; i++ )
{
   //lock x
   x = x + 1; 
   //unlock x
}

Hier lautet die Antwort jedes Mal 50.000.000.

Weitere Informationen zum Thema Sperren finden Sie unter: mutex, semaphore, critical section, shared resource.

0 Stimmen

Ver jakob.engbloms.se/archives/65 ein Beispiel für ein Programm, mit dem man testen kann, wie oft solche Dinge schief gehen... es hängt wirklich vom Speichermodell des Rechners ab, auf dem man arbeitet.

1 Stimmen

Wie kann sie 50 Millionen erreichen, wenn sie bei 10 Millionen stehen bleiben muss?

12 Stimmen

@nocomprende: Durch 5 Threads, die gleichzeitig denselben Code ausführen, wie direkt unter dem Snippet beschrieben...

197voto

Vishal Shukla Punkte 2578

Was ist eine Rennbedingung?

Sie haben vor, um 17 Uhr ins Kino zu gehen. Sie erkundigen sich nach der Verfügbarkeit der Karten für 16 Uhr. Der Mitarbeiter sagt, dass sie verfügbar sind. Sie entspannen sich und erreichen die Kasse 5 Minuten vor Beginn der Vorstellung. Sie können sich sicher denken, was passiert: Es ist ein volles Haus. Das Problem lag hier in der Zeitspanne zwischen dem Check und der Aktion. Sie haben sich um 4 Uhr erkundigt und um 5 Uhr gehandelt, und in der Zwischenzeit hat sich jemand anderes die Karten geschnappt. Das ist eine Wettlaufbedingung - genauer gesagt ein "Prüfen-dann-handeln"-Szenario von Wettlaufbedingungen.

Wie kann man sie erkennen?

Religiöse Codeüberprüfung, Multithreading-Unit-Tests. Es gibt keine Abkürzung. Es gibt ein paar Eclipse-Plugins für dieses Thema, aber noch nichts Stabiles.

Wie geht man damit um und wie verhindert man sie?

Am besten wäre es, nebenwirkungsfreie und zustandslose Funktionen zu erstellen und so viel wie möglich immutables zu verwenden. Aber das ist nicht immer möglich. Die Verwendung von java.util.concurrent.atomic, nebenläufigen Datenstrukturen, angemessener Synchronisierung und akteurbasierter Gleichzeitigkeit wird also helfen.

Die beste Ressource für Gleichzeitigkeit ist JCIP. Sie können auch einige weitere Details zur obigen Erklärung hier .

0 Stimmen

Code-Reviews und Unit-Tests sind zweitrangig, wenn es darum geht, den Datenfluss zwischen Ihren Ohren zu modellieren und weniger gemeinsamen Speicher zu verwenden.

10 Stimmen

Ich schätze das reale Beispiel einer Rennsituation

27 Stimmen

Wie die Antwort Daumen hoch . Die Lösung ist: Sie sperren die Tickets zwischen 4-5 mit Mutex (mutual exception, c++). In der realen Welt nennt man das Ticketreservierung :)

90voto

Baris Kasikci Punkte 2599

Es gibt einen wichtigen technischen Unterschied zwischen Race Conditions und Data Races. Die meisten Antworten scheinen davon auszugehen, dass diese Begriffe gleichbedeutend sind, aber das sind sie nicht.

Ein Data Race tritt auf, wenn 2 Befehle auf dieselbe Speicherstelle zugreifen, mindestens einer dieser Zugriffe ein Schreibzugriff ist und es keine geschieht vor der Bestellung unter diesen Zugriffen. Was nun eine "happens before"-Reihenfolge ausmacht, ist Gegenstand vieler Debatten, aber im Allgemeinen führen ulock-lock-Paare auf derselben lock-Variable und wait-signal-Paare auf derselben condition-Variable zu einer "happens-before"-Reihenfolge.

Eine Race Condition ist ein semantischer Fehler. Es handelt sich um einen Fehler, der in der zeitlichen Abfolge von Ereignissen auftritt und zu einer fehlerhaften Programmausführung führt. Verhalten .

Viele Wettlaufbedingungen können durch Datenwettläufe verursacht werden (und werden es auch tatsächlich), aber das ist nicht notwendig. Tatsächlich sind Datenrennen und Race Conditions weder die notwendige noch die hinreichende Bedingung füreinander. Diese In diesem Blogbeitrag wird der Unterschied anhand eines einfachen Beispiels für eine Banktransaktion ebenfalls sehr gut erklärt. Hier ist eine weitere einfache Beispiel Das erklärt den Unterschied.

Nachdem wir nun die Terminologie geklärt haben, wollen wir versuchen, die ursprüngliche Frage zu beantworten.

Da Race Conditions semantische Fehler sind, gibt es keine allgemeine Möglichkeit, sie zu erkennen. Das liegt daran, dass es keine Möglichkeit gibt, ein automatisiertes Orakel zu haben, das zwischen korrektem und inkorrektem Programmverhalten im allgemeinen Fall unterscheiden kann. Race Detection ist ein unentscheidbares Problem.

Andererseits haben Datenwettläufe eine genaue Definition, die sich nicht unbedingt auf die Korrektheit bezieht, so dass man sie erkennen kann. Es gibt viele verschiedene Arten von Data-Race-Detektoren (statische/dynamische Data-Race-Detektion, Lockset-basierte Data-Race-Detektion, happens-before-basierte Data-Race-Detektion, hybride Data-Race-Detektion). Ein hochmoderner dynamischer Data-Race-Detektor ist ThreadSanitizer was in der Praxis sehr gut funktioniert.

Der Umgang mit Datenwettläufen erfordert im Allgemeinen eine gewisse Programmierdisziplin, um zwischen den Zugriffen auf gemeinsam genutzte Daten (entweder während der Entwicklung oder sobald sie mit den oben erwähnten Werkzeugen erkannt wurden) Vorgänge auszulösen. Dies kann durch Sperren, Bedingungsvariablen, Semaphoren usw. geschehen. Man kann jedoch auch andere Programmierparadigmen wie Message Passing (anstelle von Shared Memory) verwenden, die Datenrennen von vornherein vermeiden.

0 Stimmen

Der Unterschied ist entscheidend für das Verständnis der Rassenbedingungen. Danke!

0 Stimmen

"Es ist ein Fehler, der in der zeitlichen Abfolge von Ereignissen auftritt und zu fehlerhaftem Programmverhalten führt." Perfekte Definition! Es gibt in der Tat keinen Grund für die Annahme, dass die Ereignisse innerhalb einer Instanz einer Anwendung auftreten müssen. Mehrere Instanzen sind genauso gut möglich.

48voto

Jorge Córdoba Punkte 49057

Eine Race Condition ist eine Situation bei der gleichzeitigen Programmierung, in der zwei gleichzeitige Threads oder Prozesse um eine Ressource konkurrieren und der resultierende Endzustand davon abhängt, wer die Ressource zuerst erhält.

0 Stimmen

Einfach brillante Erklärung

0 Stimmen

Endzustand von was?

2 Stimmen

@RomanAlexandrovich Der endgültige Stand des Programms. Der Zustand bezieht sich auf Dinge wie die Werte von Variablen usw. Siehe die ausgezeichnete Antwort von Lehane. Der "Zustand" in seinem Beispiel würde sich auf die Endwerte von "x" und "y" beziehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X