Thread in der Informatik einfach erklärt
Ein Thread ist ein Ausführungsstrang innerhalb eines laufenden Programms. Mehrere Threads eines Prozesses können verschiedene Aufgaben bearbeiten. Sie teilen wichtige Ressourcen, besitzen aber jeweils einen eigenen Ausführungszustand.
Auf dieser Seite lernst du, Threads von Prozessen zu unterscheiden, ihre Ausführung einzuordnen und Risiken beim gemeinsamen Datenzugriff zu erkennen.
Hake ab, was du schon kannst — und komm am Ende hierher zurück!
Was ist ein Thread?
Stell dir eine Textverarbeitung vor: Während du schreibst, kann das Programm im Hintergrund speichern und die Rechtschreibung prüfen. Solche Teilaufgaben lassen sich verschiedenen Threads zuordnen.
Thread
Ein Thread ist eine sequenzielle Folge von Programmanweisungen innerhalb eines Prozesses. Er wird auch Ausführungsstrang oder Programmfaden genannt.
Ein Thread besitzt einen eigenen Ausführungszustand. Dazu gehören insbesondere:
- ein eigener Befehlszeiger, der die nächste Anweisung bestimmt,
- eigene Register für aktuell benötigte Werte,
- ein eigener Stack für Funktionsaufrufe und lokale Daten.
Threads desselben Prozesses teilen dagegen typischerweise den Adressraum und weitere Prozessressourcen, zum Beispiel geöffnete Dateien oder Netzwerkverbindungen.
Eigener Ablauf, gemeinsame Umgebung: Jeder Thread hat seinen eigenen Ausführungszustand, arbeitet aber mit Ressourcen seines Prozesses.
Das Wort „Thread“ kann auch eine zusammengehörige Folge von Beiträgen in sozialen Medien oder Chats bezeichnen. Diese Bedeutung ist nicht technisch mit einem Programm-Thread gleichzusetzen.
Wie unterscheiden sich Thread und Prozess?
Ein Prozess ist eine laufende Instanz eines Programms. Ihm sind ein eigener Adressraum und weitere Betriebssystemressourcen zugeordnet. Ein Prozess enthält mindestens einen Thread und kann weitere Threads besitzen.
| Merkmal | Prozess | Thread |
|---|---|---|
| Rolle | Umgebung eines laufenden Programms | Ausführungsstrang innerhalb dieser Umgebung |
| Speicher | besitzt einen eigenen Adressraum | teilt den Adressraum mit Threads desselben Prozesses |
| Ausführungszustand | umfasst einen oder mehrere Threads | besitzt unter anderem eigenen Befehlszeiger, Register und Stack |
| Abschirmung | gegenüber anderen Prozessen stärker isoliert | gegenüber Threads desselben Prozesses nicht durch getrennten Adressraum isoliert |
| Datenaustausch | benötigt eine Verbindung zwischen getrennten Prozessräumen | kann gemeinsamen Speicher direkt verwenden |
Weil Threads gemeinsame Ressourcen verwenden, ist ihre Verwaltung meist weniger aufwendig als die getrennter Prozesse. Der Vorteil hat jedoch eine Kehrseite: Ein fehlerhafter Thread kann gemeinsam genutzte Daten des ganzen Prozesses beschädigen.
Ein Browser kann als Prozess laufen und mehrere Aufgaben in Threads bearbeiten. Ein Thread verarbeitet eine Eingabe, während ein anderer Daten lädt. Beide gehören zum selben Prozess und können dessen Ressourcen nutzen.
Wären die Aufgaben vollständig getrennte Prozesse, wären sie stärker voneinander abgeschirmt. Der Datenaustausch wäre dafür aufwendiger.
Welche Zustände kann ein Thread haben?
Das Betriebssystem kann nicht jeden rechenbereiten Thread jederzeit ausführen. Es verwaltet deshalb verschiedene Zustände.
| Zustand | Bedeutung |
|---|---|
| aktiv | Der Thread führt gerade Anweisungen auf einem Prozessor aus. |
| bereit | Der Thread könnte weiterarbeiten, wartet aber auf die Zuteilung von Prozessorzeit. |
| blockiert | Der Thread wartet auf ein Ereignis, zum Beispiel auf das Ende einer Ein- oder Ausgabe. |
| inaktiv | Der Thread wird eingerichtet, ist beendet oder kann entfernt beziehungsweise wiederverwendet werden. |
Ein Scheduler ist der Teil des Systems, der entscheidet, welcher bereite Thread Prozessorzeit erhält. Die genaue Reihenfolge kann sich zwischen zwei Programmläufen unterscheiden.
Ein Thread fordert Daten von einem Laufwerk an. Solange die Daten noch nicht verfügbar sind, ist er blockiert. Ein anderer bereiter Thread kann in dieser Zeit ausgeführt werden. Treffen die Daten ein, kann der wartende Thread wieder bereit werden.
Laufen mehrere Threads wirklich gleichzeitig?
Mehrere Threads können nebenläufig sein: Ihre Ausführungen überschneiden sich zeitlich. Das bedeutet nicht automatisch, dass ihre Anweisungen im selben Augenblick verarbeitet werden.
Auf einem einzelnen Prozessorkern kann der Scheduler schnell zwischen Threads wechseln. Die Ausführung ist dann zeitlich verschachtelt. Auf mehreren verfügbaren Kernen können verschiedene Threads tatsächlich gleichzeitig und damit parallel ausgeführt werden.
Nebenläufigkeit und Parallelität
Nebenläufigkeit bedeutet, dass mehrere Aufgaben in überlappenden Zeiträumen bearbeitet werden. Parallelität bedeutet, dass mindestens zwei Aufgaben im selben Zeitraum tatsächlich gleichzeitig ausgeführt werden.
Parallel ausgeführte Threads sind nebenläufig. Nebenläufige Threads müssen aber nicht parallel laufen.
Threads können eine Anwendung reaktionsfähiger machen und geeignete Aufgaben auf mehrere Kerne verteilen. Sie garantieren jedoch keinen Geschwindigkeitsgewinn. Zusätzliche Threads verursachen Verwaltungs- und Koordinationsaufwand.
Warum brauchen gemeinsame Daten Schutz?
Der Scheduler kann einen Thread zwischen einzelnen Arbeitsschritten unterbrechen. Greifen mehrere Threads ohne Abstimmung auf dieselben veränderlichen Daten zu, kann das Ergebnis deshalb von der zufälligen Reihenfolge ihrer Schritte abhängen.
Race Condition
Eine Race Condition ist eine Wettlaufsituation: Das Ergebnis hängt davon ab, in welcher Reihenfolge mehrere Threads auf gemeinsame Daten zugreifen oder sie verändern.
In einem Buchungssystem ist ein Sitz zunächst als „frei“ gespeichert.
- Thread A liest den Zustand „frei“.
- Bevor A die Reservierung speichert, liest auch Thread B den Zustand „frei“.
- Beide Threads halten eine Buchung für möglich.
- Beide speichern ihre Reservierung für denselben Sitz.
Jeder Thread hat für sich nachvollziehbar gehandelt. Zusammen erzeugen die verschachtelten Schritte aber einen falschen Zustand.
Der Teil, in dem der Sitz geprüft und reserviert wird, ist ein kritischer Abschnitt. Dort greift das Programm auf gemeinsam veränderliche Daten zu, ohne dass sich die zusammengehörigen Schritte gefahrlos überlappen dürfen.
Eine Synchronisation kann dafür sorgen, dass jeweils nur ein Thread diesen Abschnitt ausführt. Locks, Mutexe, Monitore oder Semaphore sind mögliche Mechanismen. Welcher Mechanismus passt, hängt von der Aufgabe ab.
Synchronisation soll nicht einfach möglichst viel Programmcode sperren. Ein unnötig großer geschützter Bereich kann andere Threads lange aufhalten. Ein zu kleiner Bereich schützt dagegen möglicherweise nicht alle zusammengehörigen Schritte.
Auch die Synchronisation selbst kann Fehler verursachen. Bei einem Deadlock warten Threads dauerhaft auf Ressourcen, die von den jeweils anderen gehalten werden. Bei einem Livelock bleiben Threads aktiv und reagieren aufeinander, erzielen aber keinen Fortschritt.
Karteikasten
Überlege zuerst selbst und drehe die Karte anschließend zum Prüfen um.
Alles auf einen Blick
- Thread
- eigener Ausführungszustand: Befehlszeiger, Register, Stack
- gemeinsame Prozessressourcen: Adressraum, Dateien, Verbindungen
- Zustände: aktiv, bereit, blockiert, inaktiv
- Ausführung: zeitlich verschachtelt oder auf mehreren Kernen parallel
- Nutzen: Aufgaben zerlegen und Anwendung reaktionsfähig halten
- Risiko: Race Condition bei ungeschützten gemeinsamen Daten
- Schutz: kritische Abschnitte passend synchronisieren
Abschluss-Check
Prüfe nun, ob du die zentralen Entscheidungen selbst treffen kannst.
Du hast den Kern verstanden, wenn du bei einem Beispiel drei Fragen beantworten kannst: Was besitzt der Thread selbst? Was teilt er mit anderen Threads? Welche gemeinsamen Änderungen müssen als zusammengehöriger kritischer Abschnitt geschützt werden?
Mit Google fortfahren