Ich verstehe die Grundlagen dessen, was Datenrassen sind und wie Sperren / Mutexe / Semaphoren helfen, sie zu verhindern. Aber was passiert, wenn Sie eine "Race Condition" für das Schloss selbst haben? Beispielsweise versuchen zwei verschiedene Threads, die möglicherweise in derselben Anwendung, jedoch auf unterschiedlichen Prozessoren ausgeführt werden, genau zur gleichen Zeit eine Sperre zu erlangen .
Was passiert dann? Was wird getan, um das zu verhindern? Ist es unmöglich oder einfach unwahrscheinlich? Oder ist es eine echte Rennbedingung, die darauf wartet, passiert zu werden?
multithreading
concurrency
locks
Gavin Howard
quelle
quelle
Antworten:
Unmöglich. Es kann auf verschiedene Arten implementiert werden, z. B. über Compare-and-Swap, wobei die Hardware die sequentielle Ausführung garantiert. Bei Vorhandensein mehrerer Kerne oder sogar mehrerer Sockel kann es etwas kompliziert werden, und es ist ein kompliziertes Protokoll zwischen den Kernen erforderlich , für das jedoch alles gesorgt ist.
quelle
Studieren Sie das Konzept atomarer "Test and Set" -Operationen.
Grundsätzlich kann die Operation nicht aufgeteilt werden - es ist nicht möglich, dass zwei Dinge genau zur gleichen Zeit ausgeführt werden. Es prüft einen Wert, setzt ihn, wenn er klar ist, und gibt den Wert wie beim Test zurück. Bei einer Sperroperation lautet das Ergebnis nach einem Test und Setzen immer "lock == TRUE". Der einzige Unterschied besteht darin, ob es beim Start gesetzt wurde oder nicht.
Auf Mikrocode-Ebene in einem Single-Core-Prozessor ist dies eine unteilbare Anweisung und einfach zu implementieren. Mit Mehrkern- und Mehrkernprozessoren wird es schwieriger, aber als Programmierer brauchen wir uns keine Sorgen zu machen, da es für die wirklich intelligenten Leute entwickelt wurde, die das Silizium herstellen. Im Wesentlichen machen sie dasselbe - sie machen eine atomare Anweisung, die eine ausgefallene Version von Test & Set ist
quelle
Geben Sie einfach den Code ein, um in den kritischen Bereich zu gelangen. Er wurde speziell entwickelt, damit eine Rennbedingung den gegenseitigen Ausschluss nicht verletzt.
Die meiste Zeit werden atomare Vergleichs- und Set-Schleifen verwendet, die auf Hardwareebene ausgeführt werden
In Ermangelung dessen gibt es gut untersuchte Softwarelösungen , die den gegenseitigen Ausschluss ermöglichen.
quelle
Es ist nicht möglich, dass zwei (oder mehr) Threads gleichzeitig eine Sperre erhalten. Es gibt zum Beispiel einige Arten von Synchronisationsmethoden:
Aktives Warten - Drehsperre
Pseudocode:
XCHG ist ein Beispiel für eine atomare Operation (in der x86-Architektur vorhanden), bei der zuerst ein neuer Wert für eine "Sperr" -Variable festgelegt und dann ein alter Wert zurückgegeben wird. Atomic bedeutet, dass es nicht unterbrochen werden kann - im obigen Beispiel zwischen dem Setzen eines neuen Werts und dem Zurückgeben eines alten. Atomdeterministisches Ergebnis, egal was passiert.
Wenn lock gleich 0 ist, kann ein anderer Thread in den kritischen Bereich eintreten - während die Schleife endet.
Thread-Suspending - zum Beispiel Zählen von Semaphoren
Es gibt zwei atomare Operationen
.Wait()
und.Signal()
wir haben eine Integer-Variable, die wir aufrufen könnenint currentValue
.Das Lösen von Problemen mit kritischen Abschnitten ist jetzt ganz einfach:
Pseudocode:
Normalerweise sollte Ihre Programmierthread-API Ihnen die Möglichkeit geben, maximal gleichzeitige Threads im semaphorenkritischen Abschnitt anzugeben. Offensichtlich gibt es in Multithread-Systemen (Mutex, Monitore, Binärsemaphore usw.) mehr Arten der Synchronisation, aber sie basieren auf den obigen Vorstellungen. Man könnte argumentieren, dass Methoden, die Thread-Suspending verwenden, dem aktiven Warten vorgezogen werden sollten (damit CPU nicht verschwendet wird) - es ist nicht immer die Wahrheit. Wenn der Thread angehalten wird, findet ein teurer Vorgang statt, der als Kontextwechsel bezeichnet wird. Es ist jedoch sinnvoll, wenn die Wartezeit kurz ist (Anzahl der Threads ~ Anzahl der Kerne).
quelle