Mutex-Sperre für die Kommunikation zwischen Linux-Threads (15)

1. Überblick über Synchronisierung und gegenseitigen Ausschluss

Moderne Betriebssysteme sind grundsätzlich Multitasking-Betriebssysteme, das heißt, es gibt eine große Anzahl planbarer Einheiten, die gleichzeitig ausgeführt werden. In einem Multitasking-Betriebssystem können mehrere Aufgaben gleichzeitig ausgeführt werden: Alle müssen auf dieselbe Ressource zugreifen/diese verwenden. Es bestehen Abhängigkeiten zwischen mehreren Aufgaben, die zwei Probleme verursachen können. Gegenseitiger Ausschluss: bezieht sich auf mehrere Programmfragmente, die zwischen verschiedenen Aufgaben wechseln. Wenn eine Aufgabe eines der Programmfragmente ausführt, können andere Aufgaben keines davon ausführen und können nur warten, bis die Aufgabe die Ausführung des Programms beendet hat. Die Ausführung kann erst nach dem Fragment erfolgen geschaffen. Das einfachste Szenario ist: Eine öffentliche Ressource kann jeweils nur von einem Prozess oder Thread verwendet werden, und mehrere Prozesse oder Threads können nicht gleichzeitig öffentliche Ressourcen verwenden.
Synchronisation: bezieht sich auf eine Reihe von Programmfragmenten, die zwischen verschiedenen Aufgaben wechseln. Ihr Betrieb muss in strikter Übereinstimmung mit einer bestimmten festgelegten Reihenfolge ausgeführt werden. Diese Reihenfolge hängt von den spezifischen Aufgaben ab, die ausgeführt werden müssen. Das einfachste Szenario ist: Zwei oder mehr Prozesse oder Threads koordinieren sich und werden in einer vorgegebenen Reihenfolge ausgeführt. Beispielsweise hängt der Betrieb von Aufgabe A von den von Aufgabe B generierten Daten ab. Offensichtlich ist die Synchronisation ein komplexerer gegenseitiger Ausschluss, und der gegenseitige Ausschluss ist eine besondere Art der Synchronisation. Mit anderen Worten bedeutet gegenseitiger Ausschluss, dass zwei Aufgaben nicht gleichzeitig ausgeführt werden können. Sie schließen sich gegenseitig aus. Sie müssen warten, bis ein Thread ausgeführt wird, bevor der andere ausgeführt werden kann. Die Synchronisierung kann nicht gleichzeitig ausgeführt werden, muss aber ausgeführt werden in einer bestimmten Reihenfolge erfolgen. Führen Sie den entsprechenden Thread aus (auch ein gegenseitiger Ausschluss)! Daher ist der gegenseitige Ausschluss einzigartig und exklusiv, aber der gegenseitige Ausschluss schränkt die laufende Reihenfolge der Aufgaben nicht ein, dh die Aufgaben sind ungeordnet, aber es besteht eine sequentielle Beziehung zwischen synchronisierten Aufgaben.

2. Mutex-Sperre

Einführung in die Mutex-Sperre Mutex Es gibt auch eine solche Sperre in Threads: Mutex-Sperre (Mutex) , auch Mutex genannt . Die Mutex-Sperre ist eine einfache Sperrmethode zur Steuerung des Zugriffs auf gemeinsam genutzte Ressourcen. Mutex Es gibt nur zwei Sperrzustände, nämlich Sperren und Sperren Freischalten.

Der Betriebsprozess der Mutex-Sperre ist wie folgt:
1) Sperren Sie die Mutex-Sperre nach dem Zugriff auf die gemeinsam genutzte Ressource und vor dem kritischen Bereich.
2) Lösen Sie die Sperre an der Mutex-Führung, nachdem der Zugriff abgeschlossen ist.
3) Nachdem der Mutex gesperrt wurde, wird jeder andere Thread, der versucht, den Mutex erneut zu sperren, blockiert, bis die Sperre aufgehoben wird.

Der Datentyp des Mutex ist: pthreadmutext.
Installieren Sie das entsprechende Hilfehandbuch: deng@itcast:~$ sudo apt-get install manpages-posix-dev

2.1. Initialisierungsfunktion der Mutex-Sperre

	int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

Funktion:
Initialisieren Sie eine Mutex-Sperre.

Parameter:
Mutex: Mutex-Sperradresse. Der Typ ist pthread_mutex_t.
attr: Legen Sie die Attribute des Mutex fest. Normalerweise können die Standardattribute verwendet werden, dh attr auf NULL setzen.

Sie können das Makro PTHREAD_MUTEX_INITIALIZER verwenden, um den Mutex statisch zu initialisieren, zum Beispiel:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Diese Methode entspricht dem Aufruf von pthread_mutex_init() mit dem durch NULL angegebenen Parameter attr, um die dynamische Initialisierung abzuschließen. Der Unterschied besteht darin, dass das Makro PTHREAD_MUTEX_INITIALIZER dies nicht tut Führen Sie eine Fehlerprüfung durch.

Rückgabewert:
Erfolg: 0. Die erfolgreich beantragte Sperre ist standardmäßig geöffnet.
Fehler: ungleich 0, Fehlercode.

2.2. Mutex-Sperrfunktion zerstören

	int pthread_mutex_destroy(pthread_mutex_t *mutex);

Funktion:
Zerstöre die angegebene Mutex-Sperre. Nachdem die Mutex-Sperre verwendet wurde, muss die Mutex-Sperre zerstört werden, um Ressourcen freizugeben.

Parameter:
Mutex: Mutex-Sperradresse.

Rückgabewert:
Erfolg: 0.
Fehler: ungleich 0, Fehlercode.

2.3. Sperrfunktion beantragen

	int pthread_mutex_lock(pthread_mutex_t *mutex);

Funktion:
Mutex sperren. Wenn der Mutex bereits gesperrt ist, blockiert der Aufrufer, bis der Mutex entsperrt wird, und sperrt ihn dann.

Parameter:
Mutex: Mutex-Sperradresse.

Rückgabewert:
Erfolg: 0.
Fehler: ungleich 0, Fehlercode.

veranschaulichen:

	int pthread_mutex_trylock(pthread_mutex_t *mutex);
	调用该函数时,若互斥锁未加锁,则上锁,返回 0
	若互斥锁已加锁,则函数直接返回失败,即 EBUSY

2.4.Entsperrfunktion

	int pthread_mutex_unlock(pthread_mutex_t *mutex);

Funktion:
Entsperren Sie die angegebene Mutex-Sperre.

Parameter:
Mutex: Mutex-Sperradresse.

Rückgabewert:
Erfolg: 0.
Fehler: ungleich 0, Fehlercode.

3. Referenzcode

//=============================================================================
// File Name    : thread_mutex_lock.c
// Author       : FengQQ
//
// Description  : 互斥锁
// Annotation   : 1)在访问共享资源后临界区域前,对互斥锁进行加锁。
//				  2)在访问完成后释放互斥锁导上的锁。
//				  3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,
//					 直到锁被释放。
//
// Created by FengQQ. 2020-10-04
//=============================================================================
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

pthread_mutex_t mutex;

//-----------------打印函数-----------------
void print(char *str)
{
    
    
	//hello
	while(*str != 0)
	{
    
    
		putchar(*str++);
		fflush(stdout);
		sleep(1);
	}
	printf("\n");

}
//---------------线程1入口函数---------------
void *pthread1_callback(void *arg)
{
    
    
	char buf[]="hello";
	
	pthread_mutex_lock(&mutex);		//加锁
	print(buf);
	pthread_mutex_unlock(&mutex);	//解锁
}
//---------------线程2入口函数---------------
void *pthread2_callback(void *arg)
{
    
    
	char buf[]="world";

	pthread_mutex_lock(&mutex);		//加锁
	print(buf);
	pthread_mutex_unlock(&mutex);	//解锁
}

int main(int argc,char *argv[])
{
    
    
	int ret;
	pthread_t ptid1,ptid2;
	
	ret = pthread_mutex_init(&mutex,NULL);							//互斥锁初始化
	if(ret != 0)
	{
    
    
		printf("pthread mutex init failed...\r\n");
		return -1;
	}
	
	ret = pthread_create(&ptid1,NULL,pthread1_callback,	NULL);		//创建线程1
	if(ret != 0)
	{
    
    
		printf("create new pthread1 failed...\r\n");
		return -1;
	}
	
	ret = pthread_create(&ptid2,NULL,pthread2_callback,	NULL);		//创建线程2
	if(ret != 0)
	{
    
    
		printf("create new pthread2 failed...\r\n");
		return -1;
	}
	
	ret = pthread_join(ptid1,NULL);									//回收线程1资源
	if(ret != 0)
	{
    
    
		printf("pthread1 join failed...\r\n");
	}
	
	ret = pthread_join(ptid2,NULL);									//回收线程2资源
	if(ret != 0)
	{
    
    
		printf("pthread2 join failed...\r\n");
	}
	
	return 0;
}

Lese-/Schreibsperre für die Kommunikation zwischen Linux-Threads (16)

Link: Link .(https://blog.csdn.net/qq_39721016/article/details/120477798?spm=1001.2014.3001.5501)

Guess you like

Origin blog.csdn.net/qq_39721016/article/details/120477622