Was ist ein Thread: Manchmal wird er als leichter Prozess bezeichnet und ist die kleinste Einheit des Programmausführungsablaufs.
Ein Standard-Thread besteht aus Thread-ID, aktuellem Befehlszeiger (PC), Registersatz und Stapel.
Ein Prozess besteht aus einem oder mehreren Threads. Jeder Thread teilt sich den Speicherplatz des Programms (einschließlich Codesegmente, Datensegment-Heaps usw.) und einige Ressourcen auf Prozessebene (z. B. offene Dateien und Signale)
Mehrere Threads können gleichzeitig ausgeführt werden, ohne sich gegenseitig zu stören, und globale Variablen des Prozesses und Heap-Daten gemeinsam nutzen
Zugriffsberechtigungen von Threads
Threads haben sehr freie Zugriffsrechte und können auf alle Daten im Prozessspeicher zugreifen
Thread-Planung und -Priorität
Einzelner Prozessor entspricht mehreren Threads: Das Betriebssystem lässt diese mehreren Threads nacheinander ausführen, wobei die Ausführung jedes Mal nur für einen kurzen Zeitraum (normalerweise mehrere zehn Sekunden) erfolgt, sodass jeder Thread „so aussieht“, als würde er gleichzeitig ausgeführt ; der Vorgang des kontinuierlichen Wechselns von Threads auf einem solchen Prozessor wird zur „Thread-Planung“
Es gibt drei Zustände bei der Thread-Planung:
(1): Läuft, der Thread läuft zu diesem Zeitpunkt
(2 ) : Bereit, zu diesem Zeitpunkt kann der Thread sofort ausgeführt werden, aber CPU ist belegt
(3): Zu diesem Zeitpunkt wartet der Thread auf das Eintreten eines Ereignisses und kann nicht ausgeführt werden.
Immer wenn ein Programm den Ausführungsstatus verlässt wählt einen bereiten Thread zur Ausführung aus. ;Ein Thread im Wartezustand wechselt in den Bereitschaftszustand, nachdem ein Ereignis auftritt.
Bei der Prioritätsplanung gibt es im Allgemeinen drei Möglichkeiten, die Thread-Priorität zu ändern:
Benutzerdefiniert Priorität;
Erhöhen oder verringern Sie die Priorität entsprechend der Häufigkeit des Eintritts in den Wartezustand.
Die Priorität wird erhöht, wenn sie längere Zeit nicht ausgeführt wird Linux-Multithreading
Unter Linux können Sie die folgenden drei Methoden verwenden, um eine neue Aufgabe zu erstellen:
(1) fork: Kopieren Sie den aktuellen Prozess
(2) exec: new verwenden Das ausführbare Image überschreibt das aktuelle ausführbare Image
(3) clone: Erstellen Sie einen untergeordneten Prozess und starten Sie die Ausführung vom angegebenen Speicherort aus; >pid_t pid;
if(pid==fork()){…}
Nach dem Fork-Aufruf wird eine neue Aufgabe gestartet und von der Fork-Funktion zusammen mit dieser Aufgabe zurückgegeben, aber Der Unterschied besteht darin, dass der Fork dieser Aufgabe die PID der neuen Aufgabe zurückgibt und der Fork der neuen Aufgabe 0 zurückgibt.
Fork generiert sehr schnell neue Aufgaben, da Fork den Speicherplatz nicht kopiert der ursprünglichen Aufgabe, teilt sich aber beim Schreiben den Speicherplatz von
mit der ursprünglichen Aufgabe > Beim Schreiben kopieren
: bezieht sich darauf, dass zwei Aufgaben gleichzeitig ausgeführt werden können. Lesen Sie den Speicher frei, aber wenn eine Aufgabe versucht, den Speicher zu ändern, wird der modifizierenden Partei eine Kopie des Speichers bereitgestellt zur separaten Verwendung, um die Verwendung anderer Aufgaben nicht zu beeinträchtigen;
Fork kann nur das Bild dieser Aufgabe generieren Sie müssen exec verwenden, um andere neue Aufgaben zu starten. Exec kann das aktuelle ausführbare Image durch ein neues ausführbares Image ersetzen. Nachdem Fork eine neue Aufgabe generiert hat, kann die neue Aufgabe exec aufrufen, um die neue ausführbare Datei auszuführen >Header-Dateien werden in pthread.h definiertErstellen Sie einen Thread: #include
Der Thread-Parameter ist die Kennung des neuen Threads, nachfolgende pthread_*-Funktionen verweisen über ihn auf den neuen Thread;
Der attr-Parameter wird verwendet, um die Attribute des neuen Threads festzulegen. Die Übergabe von NULL bedeutet, dass die Standard-Thread-Attribute verwendet werden.
Die Parameter Start_routine und arg geben die Funktionen und Parameter an, die der neue Thread ausführen wird ;
pthread_create gibt 0 zurück, wenn es erfolgreich ist, und einen Fehlercode, wenn es fehlschlägt;
Beenden Sie einen Thread: void pthread_exit(void *retval)
Die Funktion übergibt ihre Exit-Informationen an Recycler des Threads durch den Retval-Parameter;
Thread-Sicherheit:
Multithread-Programme befinden sich in einer sich ändernden Umgebung, und zugängliche globale Variablen und Heap-Daten können geändert werden durch andere Threads jederzeit;
Bedeutet: Synchronisierung und Sperrung
Atomar: Eine einzelne Befehlsoperation wird in jedem Fall als atomar bezeichnet wird nicht unterbrochen;
Um unvorhersehbare Folgen zu vermeiden, die dadurch entstehen, dass mehrere Threads gleichzeitig dieselben Daten lesen und schreiben, müssen wir den Zugriff jedes Threads auf dieselben Daten synchronisieren (das sogenannte Synchronisierungsmittel). Wenn ein Thread auf die Daten zugreift, bevor diese abgeschlossen sind, dürfen andere Threads nicht auf dieselben Daten zugreifen. Daher ist der Zugriff auf Daten atomar. (Semaphor, Mutex, kritischer Abschnitt, Lese-/Schreibsperre, Bedingungsvariable)
Sperre: Jeder Thread versucht zunächst, eine Sperre zu erhalten, wenn er auf Daten oder Ressourcen zugreift, und gibt die Sperre frei, nachdem der Zugriff abgeschlossen ist ;
Semaphor: Wenn ein Thread auf eine Ressource zugreift, erhält er zuerst einen Semaphor. funktioniert wie folgt: (1) Verringern Sie den Wert des Semaphors um 1; (2) Wenn der Wert des Semaphors kleiner als 0 ist, wechseln Sie in den Wartezustand. Nach dem Zugriff auf die Ressource gibt der Thread das Semaphor frei 🎜> (3) Erhöhen Sie den Wert des Semaphors um 1; (4) Wenn der Wert des Semaphors kleiner als 1 ist, wecken Sie einen wartenden ThreadMutex
&&
Semaphor
dasselbe wie: Nur Ressource Erlauben Sie einem Thread gleichzeitig den Zugriff; Ausnahme: Das Semaphor kann erworben werden und von jedem Thread im gesamten System freigegeben. Das heißt, das gleiche Semaphor kann von einem anderen Thread im System erfasst werden. Der Mutex erfordert, welcher Thread den Mutex erhält Das Aufheben der Sperre ist für andere Threads ungültig.
Kritischer Abschnitt:
ist eine strengere Synchronisierungsmethode als ein Mutex Der Erwerb Das Aufheben der Sperre im kritischen Abschnitt wird als Betreten des kritischen Abschnitts bezeichnet; das Aufheben der Sperre wird als Verlassen des kritischen Abschnitts bezeichnet. Unterschied (mit Semaphor und Mutex)Mutex und Semaphor sind in jedem Prozess des Systems sichtbar;
Das heißt, ein Prozess ist nach einem Mutex oder Semaphor erstellt, ist es für einen anderen Prozess zulässig, zu versuchen, die Sperre zu erwerben. Der Umfang des kritischen Abschnitts ist auf diesen Prozess beschränkt, und andere Prozesse können die Sperre nicht erwerben.Lesen -Schreibsperre:
Zwei Methoden: Shared ExclusiveWenn sich die Sperre im freien Zustand befindet, versuchen Sie es mit einer beliebigen Methode, um die Sperre zu erhalten kann erfolgreich sein und das Schloss in den entsprechenden Zustand versetzen (wie im Bild oben gezeigt)
Bedingungsvariable:Als Mittel zur Synchronisierung fungiert es wie ein Zaun ;
Für Bedingungsvariablen haben Threads zwei Operationen:
(1) Erstens kann der Thread auf die Bedingungsvariable warten, und eine Bedingungsvariable kann von mehreren Threads gewartet werden ( 2) Der Thread kann die Bedingungsvariable aktivieren. Zu diesem Zeitpunkt werden einer oder alle Threads, die auf diese Bedingungsvariable warten, aktiviert und unterstützen weiterhin das Auftreten eines Ereignisses. Wenn das Ereignis auftritt, können alle Threads die Ausführung gemeinsam fortsetzen. .Verwandte Artikel:
Was ist ein Prozess? Was ist ein Thread?
Basierend auf der Implementierungsmethode von Multithreading beim Java-Lernen
Das obige ist der detaillierte Inhalt vonJava lernen: Was ist ein Thread? Die ausführlichste Erklärung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!