Normalerweise heißt es, dass Multithread-Programme nicht deterministisch sind, was bedeutet, dass es bei einem Absturz fast unmöglich ist, den Fehler, der die Bedingung verursacht hat, neu zu erstellen. Man weiß nicht wirklich, welcher Thread als nächstes ausgeführt wird und wann er wieder zurückkommen wird.
Natürlich hat das mit dem OS-Thread-Scheduling-Algorithmus und der Tatsache zu tun, dass man nicht weiß, welcher Thread als nächstes ausgeführt wird und wie lange er effektiv ausgeführt wird. Die Reihenfolge der Programmausführung spielt ebenfalls eine Rolle, etc ...
Aber was wäre, wenn Sie den Algorithmus für die Thread-Planung hätten und wenn Sie wissen würden, wann welcher Thread läuft, könnte ein Multithread-Programm dann "deterministisch" werden, wie in einem Absturz?
Wenn Sie den Algorithmus kennen, können Sie nicht vorhersagen, was wann passieren wird. Alle Arten von Verzögerungen, die bei der Ausführung eines Programms oder eines Threads auftreten, hängen von den Umgebungsbedingungen ab (freies RAM - & gt; Swapping, andere Aufgaben, Interrupts, die eintreffen usw.).
Wenn Sie Ihr Multi-Thread-Programm einer sequenziellen Ausführung zuordnen würden und Ihre Threads in ihrem Verhalten deterministisch sind, könnte Ihr gesamtes Programm deterministisch sein, und "Parallelitätsprobleme" könnten reproduzierbar gemacht werden. Natürlich wären sie zu diesem Zeitpunkt keine Nebenläufigkeitsprobleme mehr.
Wenn Sie mehr erfahren möchten, Ссылка ist eine sehr interessante Lektüre.
Meine Meinung ist: technisch nicht (aber mathematisch ja). Sie können einen deterministischen Threading-Algorithmus schreiben, aber es ist extrem schwierig, den Zustand der Anwendung nach einer vernünftigen Zeitspanne vorherzusagen, die Sie behandeln können, ist nicht-deterministisch .
Es gibt einige Werkzeuge (in der Entwicklung), die versuchen werden, Rennbedingungen in einer etwas vorhersehbaren Art und Weise zu schaffen, aber es geht hier um vorausschauende Tests, nicht um die Rekonstruktion eines "Käfer in freier Wildbahn".
CHESS ist ein Beispiel.
Es wäre möglich, ein Programm auf einer virtuellen Multithread-Maschine auszuführen, bei der die Zuordnung der virtuellen Zyklen zu jedem Thread über einen vollständig deterministischen Prozess erfolgte, möglicherweise unter Verwendung eines Pseudozufallsgenerators (der mit einer Konstante gesetzt werden konnte) vor jedem Programmlauf). Eine andere, möglicherweise interessantere Möglichkeit wäre eine virtuelle Maschine, die abwechselnd Threads im "Splatter" -Modus laufen lässt (wo fast jede Variable, die sie berühren, ihren Wert zu "unbekannt" für andere Threads hätte) und "Cleanup" -Modus ( wo Ergebnisse von Operationen mit bekannten Operanden sichtbar wären und anderen Threads bekannt wären). Ich würde erwarten, dass die Situation in etwa der Hardwaresimulation ähnelt: Wenn der Ausgang jedes Gatters zwischen seiner minimalen und maximalen Laufzeit als "unbekannt" betrachtet wird, aber die Simulation trotzdem funktioniert, ist das ein gutes Indiz dafür, dass das Design robust ist Es gibt viele nützliche Designs, die nicht konstruiert werden können, um in solchen Simulationen zu funktionieren (die Zustände würden im Wesentlichen garantiert zu einer gültigen Kombination werden, obwohl man nicht garantieren könnte, welche). Dennoch könnte es ein interessanter Weg der Exploration sein, da große Teile vieler Programme so geschrieben werden können, dass sie auch in einer "Splatter-Modus" -VM korrekt funktionieren.
Normalerweise heißt es, dass Multithread-Programme nicht deterministisch sind, was bedeutet, dass es bei einem Absturz fast unmöglich ist, den Fehler, der die Bedingung verursacht hat, neu zu erstellen.
Ich stimme dem nicht zu, sichere Multithreading-Programme sind nicht deterministisch, aber auch Single-Threaded-Programme, die Benutzereingaben, Nachrichtenpumpen, Maus- / Tastatur-Handling und viele andere Faktoren berücksichtigen. Ein Multi-Thread-Programm macht es normalerweise schwieriger, den Fehler zu reproduzieren, aber definitiv nicht unmöglich. Aus welchen Gründen auch immer, Programmausführung ist nicht völlig zufällig, es gibt eine Art Wiederholbarkeit (aber keine Vorhersagbarkeit), ich kann Multi-Threaded Bugs in meinen Apps normalerweise ziemlich schnell reproduzieren, aber dann habe ich viele ausführliche Logs in meinen Apps, z die Aktionen der Endbenutzer.
Nebenbei, wenn Sie Abstürze bekommen, können Sie nicht auch Crash-Logs mit Call-Stack-Informationen bekommen? Das wird beim Debugging-Prozess sehr hilfreich sein.
Ich halte das nicht für praktikabel. Um ein spezifisches Thread-Interleaving zu erzwingen, müssen Sperren für gemeinsam genutzte Variablen platziert werden, sodass die Threads in einer bestimmten Reihenfolge auf sie zugreifen müssen. Dies würde zu schwerwiegenden Leistungseinbußen führen.
Das Wiedergeben von Nebenläufigkeitsfehlern wird normalerweise von Aufzeichnungs- und Wiedergabesystemen gehandhabt. Da die Aufzeichnung solch großer Informationsmengen auch die Leistung verschlechtert, führen die neuesten Systeme eine teilweise Protokollierung durch und vervollständigen später die Thread-Interleavings unter Verwendung von SMT-Lösung. Ich glaube, dass der jüngste Fortschritt in dieser Art von Systemen Symbiose ist (veröffentlicht in der diesjährigen PLDI-Konferenz). Tou kann Open-Source-Implementierungen in dieser URL finden:
Tags und Links multithreading non-deterministic