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

1. Übersicht über Lese-/Schreibsperren

Wenn ein Thread bereits die Mutex-Sperre hält, blockiert die Mutex-Sperre alle Threads, die versuchen, den kritischen Abschnitt zu betreten. Stellen Sie sich jedoch eine Situation vor, in der der Thread, der derzeit die Mutex-Sperre hält, nur die gemeinsam genutzte Ressource lesen und darauf zugreifen möchte und gleichzeitig mehrere andere Threads auch die gemeinsam genutzte Ressource lesen möchten. Aufgrund der Exklusivität der Mutex-Sperre jedoch alle Andere Threads Wenn die Sperre nicht erhalten werden kann, kann die gemeinsam genutzte Ressource nicht gelesen und darauf zugegriffen werden. Tatsächlich verursacht das gleichzeitige Lesen und Zugreifen mehrerer Threads auf die gemeinsam genutzte Ressource jedoch keine Probleme. Unter den Lese- und Schreibvorgängen für Daten gibt es mehr Lesevorgänge und weniger Schreibvorgänge, wie beispielsweise die Anwendung zum Lesen und Schreiben von Datenbankdaten. Um die aktuelle Anforderung zu erfüllen, mehrere Lesevorgänge, aber nur einen Schreibvorgang zuzulassen, stellt der Thread eine Lese-/Schreibsperre bereit.

Die Merkmale der Lese-/Schreibsperre sind wie folgt:
1) Wenn andere Threads Daten lesen, dürfen andere Threads Lesevorgänge ausführen, Schreibvorgänge sind jedoch nicht zulässig.
2) Wenn andere Threads Daten schreiben, dürfen andere Threads keine Lese- oder Schreibvorgänge ausführen.

Lese-/Schreibsperren werden in Lesesperren und Schreibsperren unterteilt. Die Regeln lauten wie folgt:
1) Wenn ein Thread eine Lesesperre beantragt, können andere Threads eine Lesesperre beantragen, jedoch keine Schreibsperre.
2) Wenn ein Thread eine Schreibsperre beantragt, können andere Threads keine Lesesperre oder Schreibsperre beantragen.

Der von POSIX definierte Datentyp der Lese-/Schreibsperre ist: pthreadrwlockt.

2. Initialisieren Sie die Lese-/Schreibsperrfunktion

	int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);

Funktion:
Wird zum Initialisieren der Lese-/Schreibsperre verwendet, auf die rwlock verweist.

Parameter:
rwlock: Zeiger auf die zu initialisierende Lese-/Schreibsperre.
attr: Attributzeiger der Lese-/Schreibsperre. Wenn attr NULL ist, wird die Lese-/Schreibsperre mit dem Standardattribut initialisiert, andernfalls wird die Lese-/Schreibsperre mit dem angegebenen attr initialisiert.

Hinweis:
Sie können das Makro PTHREAD_RWLOCK_INITIALIZER verwenden, um die Lese-/Schreibsperre statisch zu initialisieren, zum Beispiel:
pthread_rwlock_t my_rwlock = PTHREAD_RWLOCK_INITIALIZER;
Diese Methode entspricht dem Aufruf von pthread_rwlock_init() mit dem durch NULL angegebenen Parameter attr, um die dynamische Initialisierung abzuschließen. Der Unterschied besteht darin Das Makro PTHREAD_RWLOCK_INITIALIZER führt keine Fehlerprüfung durch.

Rückgabewert:
Erfolg: 0, der Status der Lese-/Schreibsperre wird initialisiert und entsperrt.
Fehler: ungleich 0, Fehlercode.

3. Heben Sie die Lese-/Schreibsperre auf

	int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

Funktion:
Wird verwendet, um eine Lese-/Schreibsperre zu zerstören und alle zugehörigen Ressourcen freizugeben (das sogenannte „Alle“ bezieht sich auf die Ressourcen, die von pthread_rwlock_init() automatisch beantragt werden).

Parameter:
rwlock: Lese-/Schreibsperrzeiger.

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

4. Beantragen Sie die Lesesperrfunktion

	int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

Funktion:
Erhalten Sie auf blockierende Weise eine Lesesperre (Lesesperre) für eine Lese-/Schreibsperre.
Wenn kein Schreiber die Sperre hält und kein Schreiber für die Sperre blockiert ist, erhält der aufrufende Thread die Lesesperre.
Wenn der aufrufende Thread die Lesesperre nicht erhält, blockiert er, bis er die Sperre erhält. Ein Thread kann Lesesperren mehrmals für eine Lese-/Schreibsperre ausführen.

Ein Thread kann die Funktion pthread_rwlock_rdlock() n-mal erfolgreich aufrufen, zum Entsperren muss der Thread dann jedoch n-mal die Funktion pthread_rwlock_unlock() aufrufen.

Parameter:
rwlock: Lese-/Schreibsperrzeiger.

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

veranschaulichen:

	int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
	用于尝试以非阻塞的方式来在读写锁上获取读锁。 
	如果有任何的写者持有该锁或有写者阻塞在该读写锁上,则立即失败返回。

5. Beantragen Sie die Schreibsperrfunktion

	int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

Funktion:
Erwerben Sie die Schreibsperre (Schreibsperre) für die Lese-/Schreibsperre.
Wenn kein Schreiber die Sperre hält und kein Schreiber-Leser die Sperre hält, erhält der aufrufende Thread die Schreibsperre.
Wenn der aufrufende Thread die Schreibsperre nicht erhält, blockiert er, bis er die Sperre erhält.

Parameter:
rwlock: Lese-/Schreibsperrzeiger.

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

veranschaulichen:

	int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
	用于尝试以非阻塞的方式来在读写锁上获取写锁。
	如果有任何的读者或写者持有该锁,则立即失败返回。

6. Heben Sie die Lese-/Schreibsperre auf

	int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

Funktion:
Unabhängig davon, ob es sich um eine Lesesperre oder eine Schreibsperre handelt, kann sie über diese Funktion entsperrt werden.

Parameter:
rwlock: Lese-/Schreibsperrzeiger.

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

7. Referenzcode

//=============================================================================
// File Name    : thread_mutex_rwlock.c
// Author       : FengQQ
//
// Description  : 读写锁
// Annotation   : 1)如果有其它线程读数据,则允许其它线程执行读操作,但不允许写操作。
//				  2)如果有其它线程写数据,则其它线程都不允许读、写操作。
//
// 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_rwlock_t rwlock;
static int num=0;

//---------------线程1入口函数---------------
void *pthread1_callback(void *arg)
{
    
    
	while(1)
	{
    
    
		pthread_rwlock_rdlock(&rwlock);		//加锁
		printf("pthread 1 print num %d\r\n",num++);
		sleep(5);
		printf("pthread 1 over\r\n");	
		pthread_rwlock_unlock(&rwlock);		//解锁
	}
	
}
//---------------线程2入口函数---------------
void *pthread2_callback(void *arg)
{
    
    
	while(1)
	{
    
    
		pthread_rwlock_rdlock(&rwlock);		//加锁
		printf("pthread 2 print num %d\r\n",num++);
		sleep(5);
		printf("pthread 2 over\r\n");
		pthread_rwlock_unlock(&rwlock);		//解锁
	}	
}

int main(int argc,char *argv[])
{
    
    
	int ret;
	pthread_t ptid1,ptid2;
	
	ret = pthread_rwlock_init(&rwlock,NULL);						//互斥锁初始化
	if(ret != 0)
	{
    
    
		printf("pthread rwlock 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");
	}
	
	pthread_rwlock_destroy(&rwlock);
	
	return 0;
}

Bedingungsvariablen für die Kommunikation zwischen Linux-Threads (17)

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

Guess you like

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