Die Themen kommen aus zwei Perspektiven: Betriebssysteme und Programmiersprachen. In beiden Fällen variieren die Attribute eines Threads.
Eine minimale Definition eines Threads ist, dass es sich um Dinge handelt, die nacheinander ablaufen.
In einem typischen Maschinenausführungsmodell verfügt jeder Thread über einen eigenen Satz von Allzweckregistern und einen eigenen Programmzähler. Wenn der Computer ein bestimmtes Register als Stapelzeiger ausgibt, gibt es eine Kopie pro Thread.
Aus Sicht des Betriebssystems muss ein Betriebssystem mindestens so viel tun, um Threads zu unterstützen, dass es die Möglichkeit bietet, zwischen ihnen zu wechseln. Dies kann entweder automatisch geschehen ( präventives Multitasking oder nur, wenn der Thread eine explizite Anforderung stellt (kooperatives Multitasking; in diesem Fall werden Threads manchmal als Fasern bezeichnet ) Das Wechseln zwischen Threads erfordert mindestens das Speichern der Registerwerte des alten Threads und das Wiederherstellen der Registerwerte des neuen Threads.
In einem Multitasking-Betriebssystem, das die Isolierung zwischen Aufgaben (oder Prozessen) ermöglicht , können Sie diese Begriffe als Synonyme in einem Betriebssystemkontext behandeln. Jede Aufgabe verfügt über eigene Ressourcen, insbesondere über einen Adressraum, aber auch über offene Dateien, Berechtigungen usw. Die Isolierung hat bereitgestellt durch das Betriebssystem zu Kernel , ein Unternehmen , das ist über Prozesse. Jede Aufgabe hat normalerweise mindestens einen Thread - eine Aufgabe, die keinen Code ausführt, ist wenig nützlich. Das Betriebssystem unterstützt möglicherweise mehrere Threads in derselben Task. Zum Beispiel das Original-Unix nicht. Eine Aufgabe kann immer noch mehrere Threads ausführen, indem zwischen ihnen gewechselt wird. Hierfür sind keine besonderen Berechtigungen erforderlich. Dies wird als " Benutzer-Threads" bezeichnet”, Insbesondere im Unix-Kontext. Heutzutage bieten die meisten Unix-Systeme Kernel-Threads, insbesondere weil nur so mehrere Threads desselben Prozesses auf verschiedenen Prozessoren ausgeführt werden können.
Abgesehen von der Rechenzeit sind die meisten Betriebssystemressourcen an Aufgaben und nicht an Threads gebunden. Einige Betriebssysteme (z. B. Linux) begrenzen Stapel explizit. In diesem Fall hat jeder Thread einen eigenen Thread. Aber es gibt Betriebssysteme, in denen der Kernel nichts über Stacks weiß, sie sind nur ein Teil des Haufens, was das betrifft. Der Kernel verwaltet in der Regel auch einen Kernelkontext für jeden Thread. Hierbei handelt es sich um eine Datenstruktur, die Informationen darüber enthält, was der Thread gerade tut. Auf diese Weise kann der Kernel mehrere Threads gleichzeitig verarbeiten, die in einem Systemaufruf blockiert wurden.
Für das Betriebssystem führen die Threads einer Task denselben Code aus, befinden sich jedoch an unterschiedlichen Positionen in diesem Code (unterschiedliche Programmzählerwerte). Es kann vorkommen oder nicht, dass bestimmte Teile des Codes eines Programms immer in einem bestimmten Thread ausgeführt werden, aber es gibt normalerweise allgemeinen Code (z. B. Dienstprogrammfunktionen), der von einem beliebigen Thread aus aufgerufen werden kann. Alle Threads sehen dieselben Daten, andernfalls würden sie als unterschiedliche Aufgaben betrachtet. Wenn auf einige Daten nur von einem bestimmten Thread zugegriffen werden kann, ist dies in der Regel ausschließlich die Programmiersprache, nicht das Betriebssystem.
In den meisten Programmiersprachen wird der Speicher von Threads desselben Programms gemeinsam genutzt. Dies ist ein gemeinsames Speichermodell für die gleichzeitige Programmierung. Es ist sehr beliebt, aber auch sehr fehleranfällig, da der Programmierer vorsichtig sein muss, wenn mehrere Threads auf dieselben Daten zugreifen können, da Race-Bedingungen auftreten können. Beachten Sie, dass auch lokale Variablen von mehreren Threads gemeinsam genutzt werden können: „Lokale Variable“ bedeutet (normalerweise) eine Variable, deren Name nur während einer Ausführung einer Funktion gültig ist. Ein anderer Thread kann jedoch einen Zeiger auf diese Variable abrufen und darauf zugreifen.
Es gibt auch Programmiersprachen, in denen jeder Thread seinen eigenen Speicher hat, und die Kommunikation zwischen ihnen erfolgt durch Senden von Nachrichten über Kommunikationskanäle. Dies ist das Message-Passing- Modell für die gleichzeitige Programmierung. Erlangist die Hauptprogrammiersprache, die sich auf die Weitergabe von Nachrichten konzentriert. Die Ausführungsumgebung ist sehr einfach zu handhaben und unterstützt Programme, die mit vielen kurzlebigen Threads geschrieben wurden, im Gegensatz zu den meisten anderen Programmiersprachen, bei denen das Erstellen eines Threads eine relativ teure Operation ist und die Laufzeitumgebung keine sehr großen Threads unterstützen kann Anzahl der Threads gleichzeitig. Die sequentielle Teilmenge von Erlang (der Teil der Sprache, der innerhalb eines Threads vorkommt, insbesondere die Datenmanipulation) ist (meistens) rein funktional; Auf diese Weise kann ein Thread eine Nachricht an einen anderen Thread senden, der einige Daten enthält, und keiner der Threads muss sich Sorgen machen, dass die Daten vom anderen Thread geändert werden, während er sie verwendet.
Einige Sprachen kombinieren die beiden Modelle, indem sie thread-lokalen Speicher mit oder ohne Typsystem anbieten, um den thread-lokalen Speicherort von den globalen zu unterscheiden. Thread-lokaler Speicher ist normalerweise eine praktische Funktion, mit der ein Variablenname verschiedene Speicherorte in verschiedenen Threads bestimmen kann.
Einige (schwierige) Folgemaßnahmen, die für das Verständnis der Themen von Interesse sein können:
- Was muss ein Kernel mindestens tun, um mehrere Threads zu unterstützen?
- Was ist in einer Multiprozessorumgebung erforderlich, um einen Thread von einem Prozessor auf einen anderen zu migrieren?
- Was wäre nötig, um kooperatives Multithreading ( Coroutinen ) in Ihrer bevorzugten Programmiersprache ohne Unterstützung durch das Betriebssystem und ohne die integrierte Unterstützung zu implementieren ? (Beachten Sie, dass die meisten Programmiersprachen nicht über die erforderlichen Grundfunktionen verfügen, um Coroutinen in einem einzelnen Thread zu implementieren.)
- Wie könnte eine Programmiersprache aussehen, wenn sie Parallelität, aber kein (explizites) Konzept von Threads hätte? (Paradebeispiel: der Pi-Kalkül .)