1.1 Entstehungsgeschichte
Die Menschheit kommt oft auf die Idee, ein neues, grandioses Projekt zu erschaffen, das alle vorherigen grandiosen Projekte übertrifft. Die Cheops-Pyramide in Gizeh ist die größte, der Burj Khalifa in Dubai ist der höchste, und die Chinesische Mauer ist die längste.
Doch die Arbeit an solchen Projekten zu organisieren, ist sehr schwierig. Wenn man eine neue Pyramide doppelt so hoch bauen möchte, dann benötigt man achtmal mehr Stein. Das bedeutet, man muss entweder die Produktivität der Steinbrüche erhöhen oder mehr Steinbrüche eröffnen.
Ebenso muss man achtmal mehr Ingenieure finden, möglicherweise Ingenieurschulen eröffnen, Zeichnungen, Geometrie und Schrift standardisieren. Kurz gesagt, eine ziemliche Herausforderung...
Im Laufe der tausend Jahre seit dem Bau der Pyramiden hat sich nichts geändert – die Menschen denken immer noch darüber nach, wie man immer mehr Arbeit in immer kürzerer Zeit erledigen kann. Und als Computer erfunden wurden, begannen die besten Köpfe der Menschheit, sich dieser Aufgabe zu widmen.
Wie kann man ein Programm zehnmal schneller ausführen? Eine seltsame Frage – wenn der Prozessor bereits mit maximaler Geschwindigkeit arbeitet, dann wohl kaum. Doch ich habe nicht ohne Grund die besten Köpfe der Menschheit erwähnt. Sie analysierten die Arbeit aller Programme und kamen zu dem Schluss, dass es drei große Wachstumsrichtungen gibt.
Beseitigung von Leerlaufzeiten
Es stellt sich heraus, dass ein Programm die meiste Zeit im Leerlauf ist. Es wartet ständig auf etwas: Daten müssen von einem Speicherort zum anderen kopiert werden, von der Festplatte in den Speicher geladen werden, man muss auf die Antwort eines Servers auf eine Anfrage warten, auf die Eingabe von Benutzerdaten usw.
All diese Aufgaben werden nicht vom Zentralprozessor ausgeführt, sondern von Speicher-, Festplatten-Controllern usw. Und der Zentralprozessor könnte in dieser Zeit mit etwas Nützlichem beschäftigt sein. So entstand die Idee, auf einem Prozessor nicht nur einen Befehlsausführungs-thread, sondern mehrere laufen zu lassen.
So kann beispielsweise ein Thread auf Benutzereingaben warten, während ein zweiter etwas aus dem Netzwerk herunterlädt, ein dritter Daten verarbeitet und ein vierter Bilder auf dem Bildschirm zeichnet. Daraus entwickeln sich später asynchrone Aufgaben und Coroutinen, aber dazu später mehr.
Mehr Programme
Wenn Programme 80% der Zeit im Leerlauf sind, ist das natürlich nicht gut. Andererseits, kann man nicht alle Programme mit unseren neuen Ansätzen umschreiben. Vielleicht lässt sich dieses Problem anders lösen – man kann einfach mehrere Programme auf einem Computer gleichzeitig ausführen.
In diesem Fall überwacht das Betriebssystem die Arbeit der Programme, und wenn ein Programm im Leerlauf ist, gibt es seine Ausführungszeit an ein anderes Programm weiter. Diese Umschaltung erfolgt dutzende Male pro Sekunde, und der Benutzer bemerkt die Umschaltungen schlicht nicht – aus seiner Sicht laufen die Programme gleichzeitig.
Mehr Prozessoren
Gleichzeitige Programmausführung ist cool, aber was, wenn es viele Programme gibt und sie wenig im Leerlauf sind? Kein Leerlauf – keine effiziente Nutzung. Zum Beispiel, wir haben zehn Programme, die etwas berechnen, oder ein ressourcenintensives Spiel und noch etwas dazu.
Die Lösung dieses Problems war die Hinzufügung von mehreren Prozessoren in den Prozessor. Um Verwirrung zu vermeiden, wurden sie Kerne genannt. Jetzt haben wir Prozessoren, die mehrere Kerne (Unterprozessoren) haben, auf denen dutzende Programme parallel laufen.
Interessant! Anzahl der Kerne in Prozessoren
Heutzutage können Serverprozessoren zwischen 64 und 256 Kernen haben, und in einigen spezialisierten Fällen sogar mehr. Zum Beispiel bieten AMD EPYC der 4. Generation bis zu 96 Kerne, und IBM POWER10 kann bis zu 240 Kerne pro Chip haben. Auch Endnutzerprozessoren haben sich erheblich weiterentwickelt: Hochleistungs-Desktop-CPUs wie der AMD Threadripper können bis zu 64 Kerne haben, während gebräuchlichere Modelle in der Regel zwischen 6 und 16 Kernen haben.
Wohin geht die Entwicklung weiter? Es gibt Möglichkeiten! Erstens, auf einer Server-Mainboard können mehrere Prozessoren installiert werden, zum Beispiel zwei oder sogar vier. Zweitens, können Server in Serverschränken von 10-20 Stück gebündelt werden. Und Serverschränke – in Rechenzentren, wo es Tausende solcher Schränke gibt.
Verteilte Systeme und Microservice-Architekturen sind eine gängige Praxis in der modernen Softwareentwicklung. Viele große Unternehmen wie Google, Amazon, Netflix und selbst kleinere Unternehmen nutzen verteilte Systeme, um große Datenmengen zu verarbeiten, hohe Verfügbarkeit und Skalierbarkeit ihrer Dienste sicherzustellen. Diese Systeme ermöglichen eine effiziente Nutzung der Ressourcen vieler Server, die zusammen als ein einziges Ganzes arbeiten, was die Leistung und Fehlertoleranz der Anwendungen erheblich verbessert.
1.2 Vorteile
Multithreading oder die gleichzeitige Ausführung von Aufgaben innerhalb eines Programms bietet mehrere entscheidende Vorteile, die die Leistung und Effizienz der Software erheblich verbessern können. Betrachten wir die wesentlichen Vorteile des Multithreadings.
1. Erhöhung der Leistung und Ausführungsgeschwindigkeit
Parallele Ausführung von Aufgaben: Multithreading ermöglicht die gleichzeitige Ausführung mehrerer Aufgaben, was besonders nützlich ist für Programme, die viele unabhängige Operationen ausführen müssen. Dies ermöglicht eine Beschleunigung der Programmausführung, da die Aufgaben parallel ausgeführt werden und alle verfügbaren Ressourcen des Prozessors genutzt werden.
Nutzung von Mehrkernprozessoren: Moderne Prozessoren haben mehrere Kerne, und Multithreading ermöglicht eine vollständige Nutzung ihrer Leistung, indem Threads auf verschiedene Kerne verteilt werden, um Aufgaben parallel auszuführen.
2. Verbesserung der Reaktionsfähigkeit und Benutzerinteraktion
Hintergrundaufgaben: Multithreading ermöglicht das Ausführen von langen oder ressourcenintensiven Operationen im Hintergrund, während der Hauptthread, der die Benutzeroberfläche verwaltet, reaktionsschnell bleibt. Dies verbessert die Benutzererfahrung, da die Benutzeroberfläche nicht blockiert wird bei der Ausführung schwerer Aufgaben.
Asynchrone Operationen: Die Interaktion mit dem Benutzer und die Ereignisverarbeitung können parallel zur Ausführung der Hauptaufgaben stattfinden, was Anwendungen reaktionsfähiger und effizienter macht.
3. Effektive Nutzung von Systemressourcen
Ressourcenoptimierung: Multithreading ermöglicht eine effektivere Nutzung der Systemressourcen wie Prozessorzeit und Speicher. Dies ist besonders wichtig für Server und Hochleistungs- Rechensysteme, wo Multithreading die Verarbeitung einer großen Anzahl von Anfragen und Aufgaben gleichzeitig ermöglicht.
Verwaltung von Ein- und Ausgabe: Multithread-Anwendungen können Aufgaben der Ein- und Ausgabe (z.B. Netzwerkoperationen, Lesen und Schreiben von Dateien) effektiver verwalten, da Threads andere Aufgaben ausführen können, während eine auf die Vollendung der Ein-/Ausgabeoperation wartet.
4. Unterstützung von Multitasking
Multitasking: Multithreading ermöglicht die gleichzeitige Ausführung mehrerer Aufgaben innerhalb eines Prozesses, was die Entwicklung von Anwendungen erleichtert, die Multitasking erfordern, wie Webserver, Datenbanken und Echtzeitanwendungen.
Parallele Datenverarbeitung: Bei Aufgaben, die mit der Verarbeitung großer Datenmengen verbunden sind, erlaubt Multithreading, die Daten in Teile zu zerlegen und sie parallel zu verarbeiten, was die Ausführung der Aufgabe erheblich beschleunigt.
Beispiele für die Nutzung von Multithreading
Webserver: Multithreading ermöglicht es Webservern, viele Kundenanfragen gleichzeitig zu verarbeiten, was die Leistung und Skalierbarkeit der Server erhöht.
Grafische Benutzeroberflächen (GUI): In Anwendungen mit grafischen Benutzeroberflächen ermöglicht Multithreading die Ausführung langer Berechnungen im Hintergrund, während die Benutzeroberfläche reaktionsfähig bleibt.
Wissenschaftliche Berechnungen: Multithreading wird zur parallelen Datenverarbeitung in wissenschaftlichen Berechnungen verwendet, was die Durchführung komplexer Berechnungsaufgaben erheblich beschleunigt.
Spiele und Simulationen: In Spielen ermöglicht Multithreading die gleichzeitige Verarbeitung von Physik, Grafik, Sounds und Benutzeraktionen, was die Leistung und den Realismus verbessert.
1.3 Richtiges Benennen
Zum Begriff „Multithreading“ gibt es Kritik. Er setzt sich aus zwei Wörtern zusammen: „multi“ und „thread“, und deutet darauf hin, dass innerhalb des Programms viele „Befehlsausführungs-Threads“ vorhanden sind, die etwas ausführen.
Eine schöne Analogie, aber in der englischen (originalen) Literatur wird der Begriff
„thread“ verwendet, um mehrere parallel ausgeführte Aktionen zu bezeichnen. Und entsprechend klingt Multithreading dort wie
multi-threading
.
Das könnte als kleines Missverständnis betrachtet werden – wen interessiert es,
wie verschiedene Begriffe in eine andere Sprache übersetzt werden, wenn in der Programmierung aktiv etwas wie
stream
verwendet wird, das außer mit dem Wort „Strom“
nicht übersetzt werden kann.
Daher existiert derzeit in der russischsprachigen Terminologie eine gewisse Verwirrung, die auf zwei Wegen gelöst wird:
-
Thread
(Faden) wird als „Befehlsausführungsstrom“ übersetzt. Stream
(Strom) wird als „Datenstrom“ übersetzt.
Andererseits haben viele Programmierer einfach begonnen, die englischsprachigen Begriffe ohne Übersetzung zu verwenden:
-
Thread
(Faden) wird als „Thread“ ausgesprochen, und multithreading als „Multithreading“. Stream
(Strom) wird als „Stream“ ausgesprochen.
Thread wird oft als Faden bezeichnet, aber der Begriff „mehrfädigkeit“ hat sich nicht durchgesetzt. Daher verwenden viele im Gespräch sowohl „Faden“ als auch „Multithreading“ gleichzeitig.
Die Verwendung einer großen Anzahl von Lehnwörtern macht die Sprache reicher, ermöglicht es, Wörter mit neuem Sinn zu füllen und vereinfacht die Kommunikation mit Kollegen aus anderen Ländern. Ich bin völlig für diesen Ansatz.
GO TO FULL VERSION