Multithreading

Multithreading (englisch wörtlich für Mehrfädigkeit oder auch Mehrsträngigkeit und, weiter übertragen, die Nebenläufigkeit) bezeichnet in der Informatik das gleichzeitige (oder quasi-gleichzeitige) Abarbeiten mehrerer Threads (Ausführungsstränge) innerhalb eines einzelnen Prozesses oder eines Tasks (ein Anwendungsprogramm).

Im Gegensatz zum Multitasking, bei dem mehrere unabhängige Programme voneinander abgeschottet quasi-gleichzeitig ausgeführt werden, sind die Threads eines Anwendungsprogramms nicht voneinander abgeschottet und können somit durch sogenannte Race Conditions Fehler verursachen, die durch Synchronisation vermieden werden müssen.

Sowohl Multithreading als auch Multitasking können entweder auf nur einem Prozessorkern ausgeführt werden, als auch zusätzlich mit Multiprocessing kombiniert werden (echt-parallele Ausführung durch mehrere Prozessorkerne).

Software

Seit Mehrkernprozessoren zunehmend verbreitet sind, ist softwareseitiges Multithreading rückläufig; hier ist in aller Regel nur ein Prozessorkern beteiligt – aus Sicht der Hardware (und im Allgemeinen des Betriebssystems) liegt nur ein einziger Programmausführungs-Zweig vor. Die scheinbar vorhandene Gleichzeitigkeit wird Software-intern, also innerhalb des Anwendungsprogramms und nur von ihm gesteuert, in Wirklichkeit durch geschickte Sequentialisierung („Thread“-Priorisierung) und einer logischen Abstraktion des Multiplexverfahrens erzeugt. Einzelne „Threads“ eines Prozesses/Tasks können sehr schnell auf zeitkritische Ereignisse reagieren, während andere Threads langwierige Berechnungen durchführen. Zum Beispiel kann eine Videobearbeitungs-Software eine Szene „im Hintergrund“ berechnen (Thread 1), während sie „im Vordergrund“ auf Eingaben des Benutzers reagiert (Thread 2).

Ohne weitere Hardwareunterstützung reduziert das Multithreading die Gesamtsystemleistung durch den beim Kontextwechsel entstehenden Overhead in geringem Maße; bei Abläufen, die voneinander unabhängig sein sollten, kann die Anwendung stattdessen große Performance-Schübe erwirken.

Es wird auch unterschieden, ob das Multithreading einzig im Anwendungsprogramm implementiert ist, oder ob es vom Betriebssystem unterstützt stattfindet. Ist es rein anwendungsseitig implementiert, so hat der Programmierer volle Kontrolle, wann welcher Thread welche Ressourcen erhält. Da das gesamte Programm für das Betriebssystem jedoch nur wie ein Ablauf erscheint, wird es komplett eingefroren, sobald es Ressourcen/Dienste anfordert, die gerade nicht zur Verfügung stehen – das ist das Primärproblem bei der Verarbeitung von Nutzereingaben auf einer grafischen Oberfläche und der Abarbeitung von internen Daten und Prozeduren.

Ist das Multithreading Betriebssystem-unterstützt, so kann dieses jene Teile einer Anwendung kennen, die nicht blockiert sind – die Anwendung kann (teilweise) weiterarbeiten.

Hardware

Das hardwareseitige Multithreading unterscheidet sich vom softwareseitigen dadurch, dass die Hardware eines Prozessors das scheinbare oder echte gleichzeitige Abarbeiten mehrerer Threads unterstützt. Die Software muss diese Fähigkeit verwenden und entsprechend in Threads aufgeteilt sein und diese beim Betriebssystem entsprechend anlegen/registrieren.

Moderne Betriebssysteme teilen die Last einer Multithreading-verwendenden Anwendung vollautomatisch auf alle vorhandenen Prozessorkerne auf – mit dem Höchsttakt eines einzelnen Kernes, so wird eine verbesserte Reaktivität des Betriebssystems gewährleistet als auch die Performance jeder einzelnen Anwendung erhöht.

Bei symmetrischen Multiprozessorsystemen kann die Rechenarbeit eines Prozesses/Tasks durch Multithreading auf mehrere Systemprozessoren verteilt werden.

Es muss hierbei genau unterschieden werden zwischen hardwareseitigem Multithreading und Multiprocessing. Bei Multithreading laufen die Threads im selben Task-Kontext, was für die Hardware sehr viel einfacher umzusetzen ist, z. B. wird keine zweite MMU/Seitentabelle benötigt. Bei echtem Multiprocessing ist jeder Ablauf ein eigener Prozess, jedoch könnte die Auslagerung von Threads auf physisch vorhandene Prozessorkerne ebenso als „echt nebenläufig“ eingestuft werden.

Beim hardwareseitigen Multithreading entsteht nur marginaler Overhead während des Kontextwechsels, sofern die Anzahl der Rechenzeit-fordernden Software-Threads die Anzahl Hardware-unterstützter Threads nicht übersteigt und somit jeder Thread „seine“ CPU-Ressourcen (vor allem den Registersatz) stets behalten kann.

Zusätzlich können (sowohl bei Hardware-seitigem Multithreading wie auch bei Multitasking) Prozessor-Funktionseinheiten, die von einem Rechenablauf gerade nicht verwendet werden, von einem anderen Thread verwendet werden (meist Hyper-Threading genannt). Durch die Vermeidung von Pipeline-Hazards können dabei unproduktive Taktzyklen vermieden werden, die Gesamtsystemleistung pro CPU bzw. Prozessorkern steigt.