Beispiel für einen Fork- und Mutex-Lock-Prozess im Linux-Multithreading

Beispiel für einen Fork- und Mutex-Lock-Prozess im Linux-Multithreading

Frage:

Wir haben folgendes Problem: Erstellen Sie einen untergeordneten Prozess in einem Multithread-Programm und lassen Sie子線程und子進程eine Sperre einer globalen Variable erwerben. Der untergeordnete Ausgabe-Thread erhält die Sperre und entsperrt sie dann. Der untergeordnete Prozess erhält die Sperre und entsperrt sie dann.

1. Erster Versuch

Code:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#einschließen <sys/wait.h>

pthread_mutex_t Mutex;

void*Spaß(void*Arg)
{
	pthread_mutex_lock(&mutex);	
	printf("Spaß get lock\n");
	Schlaf (3);

	pthread_mutex_unlock(&mutex);
	printf("Spaß freischalten\n");
}
int main()
{
	pthread_mutex_init(&mutex, NULL);
	pthread_t-ID;
	pthread_create(&id, NULL, Spaß, NULL);
	
	Schlaf (1);
	pid_t pid = gabel();
	wenn(pid == -1)
	{
		perror("Gabelfehler");
		Rückgabe -1;
	} 

	wenn(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("Kind erhält Sperre\n");
		Schlaf (3);
		
		pthread_mutex_unlock(&mutex);
		printf("Kind entsperren\n");
		Ausfahrt (0);
	}
	
	warte(NULL);

	pthread_mutex_destroy(&mutex);
	printf("Hauptübergabe\n");
	gebe 0 zurück;
}

Ergebnisse der Vermutung:

Sortieren Sie Ihre Gedanken:

Erstellen und initialisieren Sie eine globale Sperre
Der Hauptthread erstellt einen untergeordneten Thread, um die Sperre zu erhalten. Der Hauptthread schläft eine Sekunde lang, und der untergeordnete Thread erhält die Sperre und sperrt sie.
Der untergeordnete Thread schläft 3 Sekunden lang, gibt „Unlock Fun“ aus und der untergeordnete Thread wird beendet.
Der Hauptthread beginnt mit der Verzweigung, der untergeordnete Prozess erhält die Sperre und gibt die untergeordnete Sperre aus.
Untergeordneter Prozess zum Entsperren, Ausgabe untergeordnetes Entsperren
Der Hauptthread des übergeordneten Prozesses wartet auf das Beenden des untergeordneten Prozesses, zerstört schließlich die Sperre und gibt den Hauptthread aus.
Also … gehen Sie direkt zum richtigen Code! ! !

2. Rationale Analyse

Leider ist die Antwort falsch! ! !

我們先來康康運行結果:正常輸出了子線程的內容,但是。。。。卡住了?沒錯阻塞了。。

Bildbeschreibung hier einfügen

Nochmals analysieren:

Block? ? Könnte es sein, dass der Kindprozess beim Erwerb der Sperre blockiert wird? Oder ist der übergeordnete Prozess blockiert, während er auf den untergeordneten Prozess wartet?
Mit anderen Worten: Beide Stellen sind blockiert. Der Kindprozess wird beim Erwerb der Sperre blockiert, was zur Folge hat, dass der Elternprozess blockiert wird.
Überprüfen Sie es! !

Bildbeschreibung hier einfügen

Somit wird das Programm an zwei Stellen blockiert. Der Kindprozess wird beim Erwerb der Sperre blockiert, was wiederum eine Blockierung des Elternprozesses zur Folge hat.

3. Problemlösung

實際上,我們子線程在獲取這把鎖并加鎖后睡眠3秒,主線程睡眠1秒,在主線程1秒睡眠結束后,開始執行fork,此時的子線程還未解鎖正處于睡眠狀態,fork過程中,會直接復制父進程的所有資源(**包括這把鎖、鎖的狀態**),沒錯

就是有兩把鎖。此時子線程進行了加鎖的狀態,所以子線程復制的鎖也是加鎖狀態。所以子線程會正常退出,而子進程會因為拿到加鎖的鎖而阻塞,父進程wait因為子進程阻塞而阻塞;

(1) Verwenden von pthread_join()

Verwenden Sie pthread_join() vor dem Fork. Bevor der untergeordnete Thread endet, wird der Hauptthread blockiert und wartet, bis der untergeordnete Thread endet, bevor er forkt. Zu diesem Zeitpunkt wird die vom untergeordneten Prozess erhaltene Sperre entsperrt.

Code:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#einschließen <sys/wait.h>

pthread_mutex_t Mutex;

void*Spaß(void*Arg)
{
	pthread_mutex_lock(&mutex);	
	printf("Spaß get lock\n");
	Schlaf (3);

	pthread_mutex_unlock(&mutex);
	printf("Spaß freischalten\n");
}
int main()
{
	pthread_mutex_init(&mutex, NULL);
	pthread_t-ID;
	pthread_create(&id, NULL, Spaß, NULL);
	pthread_join(id, NULL);
	
	Schlaf (1);

	pid_t pid = gabel();
	wenn(pid == -1)
	{
		perror("Gabelfehler");
		Rückgabe -1;
	} 

	wenn(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("Kind erhält Sperre\n");
		Schlaf (3);

		pthread_mutex_unlock(&mutex);
		printf("Kind entsperren\n");
		Ausfahrt (0);
	}
	
	warte(NULL);

	pthread_mutex_destroy(&mutex);
	printf("Hauptübergabe\n");
	gebe 0 zurück;
}

Ergebnis:

Bildbeschreibung hier einfügen

(2) Verwenden Sie phread_atfork (), um ein Urteil vor der Fork zu registrieren

Header-Datei: pthread.h

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

Vorbereiten: Diese Funktion wird aufgerufen, bevor Fork ausgeführt wird

parent: Der übergeordnete Prozess ruft diese Funktion auf, nachdem Fork ausgeführt wurde

child: Der untergeordnete Prozess ruft diese Funktion auf, nachdem Fork ausgeführt wurde

Rückgabewert: 0 bei Erfolg, Fehlercode bei Fehlschlag

Code:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#einschließen <sys/wait.h>

pthread_mutex_t Mutex;

void Spaß vorbereiten(void)
{
	pthread_mutex_lock(&mutex);
}

Leere Elternspaß(Leere)
{
	pthread_mutex_unlock(&mutex);
}

void child_fun()
{
	pthread_mutex_unlock(&mutex);
}

void*Spaß(void*Arg)
{
	pthread_mutex_lock(&mutex);	
	printf("Spaß get lock\n");
	Schlaf (3);

	pthread_mutex_unlock(&mutex);
	printf("Spaß freischalten\n");
}

int main()
{
	
	pthread_mutex_init(&mutex, NULL);
	pthread_t-ID;
	pthread_atfork(Spaß vorbereiten, Spaß übergeordnet, Spaß untergeordnet);
	pthread_create(&id, NULL, Spaß, NULL);
	
	Schlaf (1);

	pid_t pid = gabel();
	wenn(pid == -1)
	{
		perror("Gabelfehler");
		Rückgabe -1;
	} 

	wenn(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("Kind erhält Sperre\n");
		Schlaf (3);

		pthread_mutex_unlock(&mutex);
		printf("Kind entsperren\n");
		Ausfahrt (0);
	}
	
	warte(NULL);

	pthread_mutex_destroy(&mutex);
	printf("Hauptübergabe\n");
	gebe 0 zurück;
}

Ergebnis:

Bildbeschreibung hier einfügen

Dies ist das Ende dieses Artikels über die Beispiele für Fork- und Mutex-Prozesse in Linux-Multithreading. Weitere relevante Inhalte zu Fork- und Mutex-Prozessen in Linux-Multithreading finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung des Python-Garbage-Collection-Mechanismus
  • Tutorial zum Prinzip des Speicherbereinigungsmechanismus für die Python-Sprachentwicklung
  • Analyse des Prinzips des Python-Garbage-Collection-Mechanismus
  • Wie wird die Garbage Collection in Python implementiert?
  • Einführung in Fork in Multithreading unter Linux
  • Python Garbage Collection und Linux Fork

<<:  Implementierung des Übergangseffekts für konkave Rechtecke mit linearem Farbverlauf in CSS

>>:  So erstellen Sie dynamische QML-Objekte in JavaScript

Artikel empfehlen

Detaillierte Erklärung gängiger Befehle im Docker-Repository

Einloggen Docker-Anmeldung Schließen Sie die Regi...

MySQL sql_mode-Analyse und Einstellungserklärung

Beim Einfügen eines Datensatzes in die MySQL-Date...

jQuery-Plugin zur Implementierung des sekundären Akkordeonmenüs

Dieser Artikel verwendet ein jQuery-Plugin, um ei...

Tutorial zur Installation von Odoo14 aus dem Quellcode unter Ubuntu 18.04

Inhaltsverzeichnis Hintergrund dieser Serie Überb...

Beispiel für das Hinzufügen und Löschen von Bereichspartitionen in MySQL 5.5

einführen Die RANGE-Partitionierung basiert auf e...

Hinweise zur Zeitverwaltung des Linux-Kernel-Gerätetreibers

/****************** * Zeitverwaltung des Linux-Ke...

MySQL Dual-Machine Hot-Standby-Implementierungslösung [testbar]

Inhaltsverzeichnis 1. Konzept 2. Umgebungsbeschre...

Zusammenfassung des Wissens über MySql-Speicher-Engines und Indizes

Speicher-Engine Was ist eine Datenbank-Speicher-E...

Detailliertes Tutorial zur Verwendung von stimulsoft.reports.js mit vue-cli

vue-cli verwendet stimulsoft.reports.js (Tutorial...

So konfigurieren Sie mehrere Tomcats mit Nginx-Lastausgleich unter Linux

Die Methoden zur Installation von Nginx und mehre...