Ich bin immer dem Konzept gefolgt, dass Multithreading nur auf Systemen mit mehreren Prozessoren implementiert werden kann, bei denen jedem Thread mehr als ein Prozessor zugewiesen werden muss und jeder Thread gleichzeitig ausgeführt werden kann. In diesem Fall gibt es keine Planung, da jeder Thread separate Ressourcen hat, die alle ihm gewidmet sind. Aber ich habe kürzlich irgendwo gelesen, dass ich Multithreading auch auf einem Einzelprozessorsystem durchführen kann. Ist es richtig? und wenn ja, was ist dann der Unterschied zwischen Systemen mit einem Prozessor und mehreren Prozessoren?
Kann Multithreading auf einem Einzelprozessorsystem implementiert werden?
Barath Ravikumar
Ich habe kürzlich irgendwo gelesen, dass ich Multithreading auch auf einem Einzelprozessorsystem ausführen kann. Ist es richtig? und wenn ja, was ist dann der Unterschied zwischen Systemen mit einem Prozessor und mehreren Prozessoren?
Ja, Sie können Multithreading auf einem Einzelprozessorsystem durchführen.
In Mehrprozessorsystemen werden mehrere Threads ausgeführt, gleichzeitig auf verschiedenen Kernen. Beispiel: Wenn zwei Threads und zwei Kerne vorhanden sind, wird jeder Thread auf einem einzelnen Kern ausgeführt.
In einem Einzelprozessorsystem werden mehrere Threads nacheinander ausgeführt oder warten, bis ein Thread beendet oder vom Betriebssystem unterbrochen wird, abhängig von der Thread-Priorität und der Betriebssystemrichtlinie. Aber die laufenden Threads erwecken die Illusion, dass sie gleichzeitig ausgeführt werden , relativ zur erforderlichen Reaktionszeit der Anwendung der Benutzerbereichsanwendung.
Zeitvergleich (Beispiel):
Wenn zwei Threads jeweils 10 us für die Ausführung benötigen, beträgt die Nettozeit auf einem 2-Prozessor-System 10 us
Wenn zwei Threads jeweils 10 us für die Ausführung benötigen, beträgt die Nettozeit auf einem 1-Prozessor-System 20 us
-
sehr hilfreich. Vielen Dank 🙂
– Ayse
20. April 2013 um 5:46 Uhr
-
Chrome führt Tabs aus Prozesse, keine Fäden. Die Behauptung, dass Threads die Stabilität verbessern, ist falsch. Es ist nicht möglich, dass ein Thread abstürzt und den Rest laufen lässt. Da sich alle Threads eines Prozesses einen gemeinsamen Adressraum teilen, sind sie möglicherweise alle von einem Thread betroffen, der den Speicher überlastet. Darüber hinaus beendet eine unfreiwillige Beendigung, die durch einen “Absturz” eines Threads verursacht wird, den gesamten Prozess, nicht nur einen einzelnen Thread.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
20. April 2013 um 5:54 Uhr
-
@R .. Ok, ich habe den kontroversen Teil entfernt … vielleicht habe ich nicht genug gelesen, um die Stabilität von Threads zu sichern und zu rechtfertigen …
– Barath Ravikumar
20. April 2013 um 6:01 Uhr
-
Die einzige Möglichkeit, ein Argument dafür zu sehen, dass Threads “die Stabilität verbessern”, besteht darin, den Code zu vereinfachen und Fehler weniger wahrscheinlich zu machen. Es ist viel einfacher, synchrone Logik zu schreiben, die in einem eigenen Thread läuft, als asynchrone, ereignisgesteuerte Zustandsmaschinenlogik, und dies könnte zu sichereren, stabileren Programmen führen. Threads geben Ihnen jedoch keine Sicherheit, wenn einer von ihnen UB aufruft.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
20. April 2013 um 6:04 Uhr
-
Ich denke, BarathBushans Antwort ist hilfreich und die Leute sollten es vermeiden, sie abzulehnen 🙁
– Ayse
20. April 2013 um 6:22 Uhr
Natürlich geht das auch auf einem Einprozessorsystem, und tatsächlich ist es so viel einfacher. Es funktioniert genauso wie das Ausführen mehrerer Prozesse – der Kernel hält über einen Timer-Interrupt oder einen ähnlichen Mechanismus einen an, speichert seinen Maschinenzustand und ersetzt diesen durch den zuvor gespeicherten Zustand eines anderen – der einzige Unterschied sind diese beiden Threads desselben Prozesses teilen sich denselben virtuellen Speicherplatz, wodurch der Task-Wechsel viel effizienter wird.
Multi-Threading auf Mehrprozessorsystemen ist tatsächlich viel schwieriger, da Sie Probleme mit dem gleichzeitigen Zugriff auf den Speicher von mehreren CPUs/Kernen und all den unangenehmen Problemen mit der Speichersynchronisierung haben, die sich daraus ergeben.
-
Ich danke dir sehr. Das war hilfreich
– Ayse
20. April 2013 um 5:45 Uhr
-
Nein, das müssen Sie falsch verstehen, denn die Aussage, wie Sie sie paraphrasiert haben, ist definitiv falsch.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
20. April 2013 um 12:37 Uhr
-
⁺¹ für den «Timer-Interrupt». Whole Internet erwähnt nicht, wie genau die Umschaltung in Hardware erfolgt; Ich nahm an, dass es sich um eine Art Timer handelt, aber selbst die Wikipedia schweigt.
– Hallo Engel
10. März 2016 um 13:48 Uhr
-
Wenn 2 Threads auf einem Prozessor laufen … ist keine Synchronisierung erforderlich?
– Benutzer2156081
24. Dezember 2016 um 20:23 Uhr
-
Habe die Antwort von @Barath post bekommen.
– Benutzer2156081
24. Dezember 2016 um 20:27 Uhr
Auf einem Quad-Core-System können mehr als vier aktive Threads vorhanden sein. Dort ist Scheduling, es sei denn, Sie können garantieren, dass Prozesse nicht versuchen, mehr Threads zu erstellen, als Prozessoren vorhanden sind.
Ja, Sie können mehrere Threads auf einem Single-Core-Computer haben.
Der Unterschied zwischen Einprozessor- und Mehrprozessorsystemen besteht darin, dass ein Mehrprozessorsystem tatsächlich mehr als eine Sache gleichzeitig erledigen kann. Es kann N Dinge gleichzeitig tun, wobei N die Anzahl der Prozessorkerne ist. Ein Single-Prozessor-Kern kann nur eine Sache gleichzeitig tun. Wie WhozCraig in seinem Kommentar sagte, ist es der Unterschied zwischen tatsächlicher und wahrgenommener Parallelität.
-
Vielen Dank, ich habe jetzt die Grundidee, wie die Dinge gemacht werden
– Ayse
20. April 2013 um 5:45 Uhr
Ja, das kannst du absolut. Vor Ewigkeiten (Win 95?) sind wir von kooperativem Multitasking auf Multithreading umgestiegen, weil immer jemand den kooperativen Teil vermasselt hat. Jedes Programm auf Ihrem Computer hat mindestens einen Thread. Möglicherweise mehr. Und die CPU wechselt wie verrückt ein paar Millionen Mal pro Sekunde zwischen all diesen Threads. Wenn keiner von ihnen etwas zu tun hat, kann es sogar sein, dass es einige Zeit stillsteht.
Multicore-Systeme bedeuten nur, dass zwei oder mehr dieser Threads parallel laufen können.
Allerdings bringt es Ihnen viel weniger, dies zu tun. Alles, was Sie mit Multithreading auf einem Single-Core-Computer tun können, ist Multitasking zu simulieren.
Multitasking reicht aus, um zu verhindern, dass der GUI-Thread aufgrund einer lang andauernden Operation blockiert. Es ist jedoch im Allgemeinen kompliziert zu implementieren, es sei denn, Sie haben Hilfe vom Compiler oder der Sprache (wie C # async … warten). Infolgedessen verwendeten viele GUI-Programmierer nur Multithreading und Invoking, um Multitasking vorzutäuschen. Ob dieser Code auf einem oder mehreren Kernen läuft, spielt keine Rolle.
Am wichtigsten ist, dass Multitasking NICHT für CPU-gebundene Operationen geeignet ist. Aber 95 % aller Async-Probleme sind nicht CPU-gebunden. Sie sind netzwerk- oder festplattengebunden. Auf einem Singlecore-Computer hilft Multithreading auch nicht bei CPU-gebundenen Dingen. Wenn Sie zwei Threads haben, die beide 100 % CPU-Zeit benötigen (dasselbe Programm oder ein anderes), aber nur einen Kern, um sie auszuführen, muss die CPU nur zwischen der Ausführung beider mit 49 % wechseln und die verbleibenden 2 % für all diese verwenden andere Threads, die nur ein bisschen tun.
Schließlich können nur sehr wenige Probleme tatsächlich Multithreaded werden. Versuchen Sie einfach, die Fibonacci-Folge zu multithreaden (ein Thread für jedes Paar), ohne sie langsamer, speicherintensiver und komplexer zu machen.
tl;dr; Sie benötigen Multithreading und einen Multicore-Computer für CPU-gebundene Probleme. Die meisten asynchronen Probleme sind nicht CPU-gebunden. Multitasking reicht völlig aus. Und Sie können mithilfe von Threads vollständig multitasken, sogar auf einem Computer mit einem Kern.
Luser Drog
Hier ist ein sehr vereinfachtes Beispiel. Es ist eigentlich ein Prototyp für ein Programm, das ich baue. Es ist eine Implementierung von kooperativem Multitasking in einem einzigen Thread.
main
setzt einfach die quit
Flag auf false und füllt ein Array von Funktionszeigern (die Aufgaben) und ruft dann auf loop
.
loop
Verwendet setjmp
um einen Rückkehrpunkt für einen nicht-lokalen Sprung zu setzen (ein jump aus der Funktion zurück zu einer vorherigen Position in der Ausführung) und fährt dann fort, die erste Aufgabe (Funktion) aufzurufen.
Jede Aufgabe endet mit yield()
. Das heißt, keine der Aufgaben funktioniert tatsächlich return
. Sie enthalten nicht nur keine a return;
Aussage (was in Ordnung wäre, da sie es sind void
Funktionen, dh. Verfahren), aber sie würden die nicht erreichen return
auch wenn es da war yield
springt zurück zum setjmp
Anruf, diesmal mit einer 1 für die if
Aussage ein loop
. Die Anweisung, die von der gesteuert wird if
Anweisung wählt eine andere Aufgabe aus, bevor Sie die erneut eingeben while
Schleife.
Jede Task-Funktion wird also mehrmals ausgeführt, was zu dem führt Dispatcher (das if(setjmp...
-Anweisung), die eine neue auszuführende Aufgabe auswählt.
#include <stdio.h>
#include <setjmp.h>
jmp_buf dispatch;
int ntasks;
void (*task[10])(void);
int quit;
void yield(void) {
longjmp(dispatch, 1);
}
void loop() {
static int i = 0;
if(setjmp(dispatch))
i = (i+1) % ntasks;
while(!quit)
task[i]();
}
int acc = 0;
void a(void) {
if (acc > 10) quit = 1;
printf("A\n");
yield();
}
void b(void) {
acc *= 2;
printf("B\n");
yield();
}
void c(void) {
acc += 1;
printf("C\n");
yield();
}
int main() {
quit = 0;
ntasks = 3;
task[0] = a;
task[1] = b;
task[2] = c;
loop();
return 0;
}
Der Unterschied zwischen diesem Beispiel und einem Einzelprozessor-Multitasking-Computersystem besteht darin, dass der reale Prozessor das Unterbrechen einer Aufgabe mitten in der Ausführung und deren spätere Wiederaufnahme an derselben Stelle unterstützt. Dies ist in einer C-Simulation mit Aufgaben als einzelne Funktionen nicht wirklich möglich. Die Tasks könnten jedoch aus einer Folge von C-Funktionen bestehen, die jeweils an den Dispatcher übergeben werden (vielleicht ein Array von Funktionszeigern oder eine verkettete Liste).
-
Können Sie bitte eine Art Beschreibung oder Kommentar hinzufügen, um genau zu erklären, was dies zeigen und tun soll? Vielen Dank.
– Deanna
26. April 2013 um 12:52 Uhr
-
Mit einigen Erläuterungen bearbeitet. (Bei Bedarf kann ich weitere hinzufügen.)
– Luser Drog
26. April 2013 um 13:10 Uhr
-
Es sieht nicht so aus, als gäbe es eine Möglichkeit, von a zurückzukehren
yield()
, also muss jeder Thread abgeschlossen werden, bevor er yield aufruft. Es gibt also keine Möglichkeit, mehr als einen Live-Thread gleichzeitig zu haben und zwischen ihnen zu wechseln. Sie könnten die Dinge also viel einfacher machen, indem Sie die Aufgaben einfach zurückgeben (anstatt yield aufzurufen) und nicht verwendensetjmp
/longjmp
überhaupt.– Chris Dodd
20. September 2013 um 1:07 Uhr
Neethu Lalitha
In einem Multithread-Prozess auf einem einzelnen Prozessor kann der Prozessor Ausführungsressourcen zwischen Threads wechseln, was zu einer gleichzeitigen Ausführung führt. Parallelität gibt an, dass mehr als ein Thread Fortschritte macht, die Threads jedoch nicht gleichzeitig ausgeführt werden. Das Umschalten zwischen Threads erfolgt schnell genug, dass die Threads scheinbar gleichzeitig ausgeführt werden.
In demselben Multithread-Prozess in einer Mehrprozessorumgebung mit gemeinsam genutztem Speicher kann jeder Thread im Prozess gleichzeitig auf einem separaten Prozessor ausgeführt werden, was zu einer parallelen Ausführung führt, die eine echte simultane Ausführung ist. Wenn die Anzahl der Threads in einem Prozess kleiner oder gleich der Anzahl der verfügbaren Prozessoren ist, stellt das Thread-Unterstützungssystem des Betriebssystems sicher, dass jeder Thread auf einem anderen Prozessor ausgeführt wird. Beispielsweise kann bei einer Matrixmultiplikation, die mit vier Threads programmiert ist und auf einem System mit zwei Dual-Core-Prozessoren läuft, jeder Software-Thread gleichzeitig auf den vier Prozessorkernen laufen, um gleichzeitig eine Reihe des Ergebnisses zu berechnen.
-
Können Sie bitte eine Art Beschreibung oder Kommentar hinzufügen, um genau zu erklären, was dies zeigen und tun soll? Vielen Dank.
– Deanna
26. April 2013 um 12:52 Uhr
-
Mit einigen Erläuterungen bearbeitet. (Bei Bedarf kann ich weitere hinzufügen.)
– Luser Drog
26. April 2013 um 13:10 Uhr
-
Es sieht nicht so aus, als gäbe es eine Möglichkeit, von a zurückzukehren
yield()
, also muss jeder Thread abgeschlossen werden, bevor er yield aufruft. Es gibt also keine Möglichkeit, mehr als einen Live-Thread gleichzeitig zu haben und zwischen ihnen zu wechseln. Sie könnten die Dinge also viel einfacher machen, indem Sie die Aufgaben einfach zurückgeben (anstatt yield aufzurufen) und nicht verwendensetjmp
/longjmp
überhaupt.– Chris Dodd
20. September 2013 um 1:07 Uhr
Ja, und um es einfach auszudrücken, wahrgenommene vs. tatsächliche Parallelität.
– WhozCraig
20. April 2013 um 5:29 Uhr
Wenn es nicht möglich wäre, dann war Windows 95 eine Massenhalluzination. (Wenn Sie Multiprocessing als Multithreading zählen, dann war das ursprüngliche Unix auch eine Massenhalluzination.)
– Raymond Chen
20. April 2013 um 16:19 Uhr
https://stackoverflow.com/questions/16116952/can-multithreading-be-implemented-on-a-single-processor-system (qnx.com/developers/docs/qnxcar2/…) Bilder stärker als Worte
– LinconFive
15. Mai 2020 um 2:03 Uhr