


Detaillierte Einführung in die Multithread-Programmierung in C-Sprache unter Linux
In diesem Artikel wird hauptsächlich die Multithread-Programmierung in C-Sprache unter Linux vorgestellt. Freunde, die es benötigen, können darauf verweisen
Wenn wir Linux-Dienste schreiben, verwenden wir häufig die Linux-Multithreading-Technologie, um die Programmleistung zu verbessern
Einige Tipps zum Multithreading:
Eine Anwendung kann mehrere Threads starten.
Thread (Lightweight Process, LWP) ist die kleinste Einheit der Programmausführung.
Im Allgemeinen verfügt das einfachste Programm über mindestens einen Thread, bei dem es sich um das Programm selbst handelt, dh um die Hauptfunktion (ein Single-Thread-Prozess kann einfach als Prozess mit nur einem Thread betrachtet werden)
Ein Thread ist blockiert. Andere Threads sind davon nicht betroffen.
Multithread-Prozesse können die CPU-Ressourcen des Systems so weit wie möglich nutzen.
1 Erstellen Sie einen Thread
Beginnen wir zunächst mit einem einfachen Code, der einen Thread in einem Prozess erstellt, und gehen wir dann tiefer.
#include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void * func(void * arg) { printf("func run...\n"); return NULL; } int main() { pthread_t t1; int err = pthread_create(&t1,NULL,func,NULL); if(err!=0) { printf("thread_create Failed:%s\n",strerror(errno)); }else{ printf("thread_create success\n"); } sleep(1); return EXIT_SUCCESS; } int pthread_create(pthread_t *thread,const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
In der Hauptfunktion rufen wir die obige Funktion auf, um einen Thread zu erstellen.
Funktionsparameter:
Der erste Parameter: pthread_t stellt die eindeutige Kennung des erstellten Threads dar. Nachdem wir ihn erstellt haben, müssen wir ihn ändern Der Zeiger wird übergeben.
Der zweite Parameter: pthread_attr_t, stellt einige Konfigurationen zum Erstellen dieses Threads dar, z. B. die Größe des Zuordnungsstapels usw. . Im Allgemeinen können wir NULL eingeben, was die Standardkonfiguration für die Thread-Erstellung darstellt.
Der dritte Parameter: stellt die Adresse einer Funktion dar. Beim Erstellen eines Threads wird diese Funktion aufgerufen *, die Parameter der Funktion. Auch void*, das allgemeine Format ist wie folgt: void * func(void * arg){}
Der vierte Parameter: stellt den Parameter dar, der durch den Aufruf der dritten Funktion
Funktionsrückgabe übergeben wird Wert:
Die Funktion gibt erfolgreich 0 zurück. Wenn sie nicht gleich 0 ist, bedeutet dies, dass der Funktionsaufruf fehlgeschlagen ist. Zu diesem Zeitpunkt kann strerror(errno) verwendet werden, um den spezifischen Fehler auszudrucken.
Hinweis: Jeder Thread hat eine Kopie von errno, und verschiedene Threads haben unterschiedliche errno
Endlich zusammengestellt von gcc
gcc 1createthread.c -c -o 1createthread.o gcc 1createthread.o -o thr1 -lpthread
Beim Kompilieren müssen Sie -lpthread hinzufügen, um die dynamische Bibliothek libpthread.so zu verknüpfen. Andernfalls wird angezeigt, dass die Funktion nicht gefunden werden kann
Der Funktionsaufruf gibt das Ergebnis zurück
Frage: Warum wird die Schlaffunktion aufgerufen? Alle Threads werden beendet.
2 Threads hängen
Manchmal erstellen wir einen weiteren Thread in einem Thread und der Hauptthread muss warten, bis der erstellte Thread zurückkehrt Der Hauptthread wird erst beendet, nachdem der Rückgabewert des Threads erhalten wurde. Zu diesem Zeitpunkt müssen Sie eine Fadenaufhängung verwenden.
Die Funktion pthread_join wird verwendet, um den aktuellen Thread anzuhalten, bis der durch th angegebene Thread beendet wird.
int pthread_join(pthread_t th, void **thr_return);。
Ergebnis der Funktionsausführung
#include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void * func(void * arg) { int i=0; for(;i<5;i++) { printf("func run%d\n",i); sleep(1); } int * p = (int *)malloc(sizeof(int)); *p=11; return p; } int main() { pthread_t t1,t2; int err = pthread_create(&t1,NULL,func,NULL); if(err!=0) { printf("thread_create Failed:%s\n",strerror(errno)); }else{ printf("thread_create success\n"); } void *p=NULL; pthread_join(t1,&p); printf("线程退出:code=%d\n",*(int*)p); return EXIT_SUCCESS; }
3 Thread-Beendigung
Exit()-Funktion, wenn der Prozess beendet wird, also was ist Thread-Beendigung? Drei Situationen der Thread-Beendigung:
Der Thread kehrt einfach von der Startfunktion zurück und der Rückgabewert ist der Exit-Code des Threads.
Threads können von anderen Threads im selben Prozess abgebrochen werden.
Der Thread ruft pthread_exit auf.
Die Parameter der pthread_exit-Funktion sind die gleichen wie bei der Rückgabe des normalen Thread-Endes und werden vom Haupt-Thread abgerufen, der auf sein Ende wartet.
#include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void * func(void * arg) { int i=0; while(1) { if(i==10) { int * p = (int *)malloc(sizeof(int)); *p=11; pthread_exit(p); } printf("fun run %d\n",i++); sleep(1); } return NULL; } int main() { pthread_t t1,t2; int err = pthread_create(&t1,NULL,func,NULL); if(err!=0) { printf("thread_create Failed:%s\n",strerror(errno)); }else{ printf("thread_create success\n"); } void *p=NULL; pthread_join(t1,&p); printf("线程退出:code=%d",*(int*)p); return EXIT_SUCCESS; } void pthread_exit(void *arg);
4-Thread-Trennung
Die Funktion pthread_detach versetzt den Thread in einen getrennten Zustand.
int pthread_detach(pthread_t th);
Ein Thread kann pthread_detach nicht selbst aufrufen, um sich in den getrennten Zustand zu versetzen. Er kann pthread_detach nur von anderen Threads aufrufen.
5 Thread-Abbruch
Die pthread_cancel-Funktion ermöglicht es einem Thread, einen anderen Thread abzubrechen, der durch angegeben wird Thread.
int pthread_cancel(pthread_t th);
Ergebnis der Funktionsausführung:
#include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void * func1(void * arg) { while(1) { printf("fun run...\n"); sleep(1); } return NULL; } int main() { pthread_t t1; if(pthread_create(&t1,NULL,func1,NULL)!=0) { printf("thread_create Failed:%s\n",strerror(errno)); return -1; } sleep(5); pthread_cancel(t1); pthread_join(t1,NULL); return EXIT_SUCCESS; }
上面我们说过创建一个线程函数pthread_create的第二个参数,用来决定创建线程的一些初始化状态,这里我们 举个例子,改线程一创建就是分离状态的线程(
上面介绍了pthread_detach函数的概念,可以通过pthread_attr_t在创建线程的时候就指定线程属性为detach,而不用创建以后再去修改线程属性。
)
先上一段代码:
#include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void * func(void * arg) { int i=0; for(;i<5;i++) { printf("func run%d\n",i); sleep(1); } int * p = (int *)malloc(sizeof(int)); *p=11; return p; } int main() { pthread_t t1; pthread_attr_t attr;//申明一个attr的结构体 pthread_attr_init(&attr);//初始化结构体 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//设置线程为分离线程 int err = pthread_create(&t1,&attr,func,NULL); if(err!=0) { printf("thread_create Failed:%s\n",strerror(errno)); }else{ printf("thread_create success\n"); } pthread_attr_destroy(&attr); pthread_join(t1,NULL); printf("主线程退出\n"); return EXIT_SUCCESS; }
pthread_attr_t就是我们要传入的参数的结构体,一般申明的步骤有
1,申明一个pthread_attr_t对象
2,函数pthread_attr_init初始化attr结构。
3,设置线程的一些属性,比如pthread_attr_setdetachstate函数就是设置该线程创建的时候为正常状态还是分离状态。
4,函数pthread_attr_destroy释放attr内存空间
pthread_attr_setdetachstate把线程属性设置为下面两个合法值之一:
值 | 说明 |
PTHREAD_CREATE_DETACHED | 设置线程为分离状态 |
PTHREAD_CREATE_JOINABLE | 设置线程为正常状态 |
上面函数运行结果:
因为线程是个分离状态的,所以pthread_join挂起会失效,主线程很快运行结束,程序也就结束了,创建的线程还没来得及运行
线程同步
有时候我们多个线程处理订单扣减库存会遇到这样的问题,两个线程同时进入一段代码先查询库存,两个都查出来为还剩一件库存,第一个线程用掉这个库存后,将库存变为0,但是第二个线程刚才也查出来为1了,所以他还认为有库存,
这个时候操作就会引发我们想不到的意外,库存变为负数了!!所以这个时候就需要使用线程的同步!!
先上一段代码看看效果:
#include<pthread.h> #include<stdio.h> #include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void * func(void * arg) { int threadno =*(int*)arg; int i=0; for(;i<10;i++) { printf("%d thread%d \n",threadno,i); sleep(1); } return NULL; } int main() { pthread_t t1,t2; int i1=1,i2=2; pthread_create(&t1,NULL,func,&i1); pthread_create(&t2,NULL,func,&i2); pthread_join(t1,NULL); pthread_join(t2,NULL); printf("主线程退出\n"); return EXIT_SUCCESS; }
函数运行结果:
可以看到两个线程是没有规律的争相处理的,如果这段代码是扣减库存就完蛋啦!,所以我们要对这段代码进行加锁,同一时刻只能有一个线程进入操作!
先上代码:
#include<pthread.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void * func(void * arg) { pthread_mutex_lock(&mutex);//对mutex加锁,其他线程进入后将会挂起,知道这个锁被解锁 int threadno =*(int*)arg; int i=0; for(;i<10;i++) { printf("%d thread%d \n",threadno,i); sleep(1); } pthread_mutex_unlock(&mutex); return NULL; } int main() { pthread_t t1,t2; int i1=1,i2=2; pthread_create(&t1,NULL,func,&i1); pthread_create(&t2,NULL,func,&i2); pthread_join(t1,NULL); pthread_join(t2,NULL); printf("主线程退出\n"); return EXIT_SUCCESS; }
函数运行结果:
可以看到第二个线程先进入后一直运行结束,对mutex解锁后,第一个线程才能进方法里面运行!否则会挂起,一直等到锁被解锁!
PTHREAD_MUTEX_INITIALIZER是初始化一个快速锁的宏定义。
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
加锁解锁函数:
int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
总结
Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in die Multithread-Programmierung in C-Sprache unter Linux. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Schritte zum Starten von Nginx unter Linux: Überprüfen Sie, ob Nginx installiert ist. Verwenden Sie SystemCTL Start Nginx, um den Nginx -Dienst zu starten. Verwenden Sie SystemCTL aktivieren NGINX, um das automatische Start von NGINX beim Systemstart zu aktivieren. Verwenden Sie den SystemCTL -Status NGINX, um zu überprüfen, ob das Startup erfolgreich ist. Besuchen Sie http: // localhost in einem Webbrowser, um die Standard -Begrüßungsseite anzuzeigen.

So bestätigen Sie, ob Nginx gestartet wird: 1. Verwenden Sie die Befehlszeile: SystemCTL Status Nginx (Linux/Unix), Netstat -ano | FindStr 80 (Windows); 2. Überprüfen Sie, ob Port 80 geöffnet ist; 3. Überprüfen Sie die Nginx -Startmeldung im Systemprotokoll. 4. Verwenden Sie Tools von Drittanbietern wie Nagios, Zabbix und Icinga.

Verwenden Sie unter Linux den folgenden Befehl, um zu überprüfen, ob Nginx gestartet wird: SystemCTL -Status Nginx Richter basierend auf der Befehlsausgabe: Wenn "aktiv: aktiv (lief) angezeigt wird, wird Nginx gestartet. Wenn "Active: Inactive (Dead)" angezeigt wird, wird Nginx gestoppt.

Der Server verfügt nicht über die Berechtigung, auf die angeforderte Ressource zuzugreifen, was zu einem NGINX 403 -Fehler führt. Zu den Lösungen gehören: Überprüfung der Dateiberechtigungen. Überprüfen Sie die Konfiguration .htaccess. Überprüfen Sie die Nginx -Konfiguration. Konfigurieren Sie Selinux -Berechtigungen. Überprüfen Sie die Firewall -Regeln. Fehlerbehebung bei anderen Ursachen wie Browserproblemen, Serverausfällen oder anderen möglichen Fehlern.

Die wichtigsten Unterschiede zwischen CentOS und Ubuntu sind: Ursprung (CentOS stammt von Red Hat, für Unternehmen; Ubuntu stammt aus Debian, für Einzelpersonen), Packungsmanagement (CentOS verwendet yum, konzentriert sich auf Stabilität; Ubuntu verwendet apt, für hohe Aktualisierungsfrequenz), Support Cycle (Centos) (CENTOS bieten 10 Jahre. Tutorials und Dokumente), Verwendungen (CentOS ist auf Server voreingenommen, Ubuntu ist für Server und Desktops geeignet). Weitere Unterschiede sind die Einfachheit der Installation (CentOS ist dünn)

Docker verwendet Linux -Kernel -Funktionen, um eine effiziente und isolierte Anwendungsumgebung zu bieten. Sein Arbeitsprinzip lautet wie folgt: 1. Der Spiegel wird als schreibgeschützte Vorlage verwendet, die alles enthält, was Sie für die Ausführung der Anwendung benötigen. 2. Das Union File System (UnionFS) stapelt mehrere Dateisysteme, speichert nur die Unterschiede, speichert Platz und beschleunigt. 3. Der Daemon verwaltet die Spiegel und Container, und der Kunde verwendet sie für die Interaktion. 4. Namespaces und CGroups implementieren Container -Isolation und Ressourcenbeschränkungen; 5. Mehrere Netzwerkmodi unterstützen die Containerverbindung. Nur wenn Sie diese Kernkonzepte verstehen, können Sie Docker besser nutzen.

CentOS wird 2024 geschlossen, da seine stromaufwärts gelegene Verteilung RHEL 8 geschlossen wurde. Diese Abschaltung wirkt sich auf das CentOS 8 -System aus und verhindert, dass es weiterhin Aktualisierungen erhalten. Benutzer sollten eine Migration planen, und empfohlene Optionen umfassen CentOS Stream, Almalinux und Rocky Linux, um das System sicher und stabil zu halten.

Frage: Wie starte ich Nginx? Antwort: Installieren Sie Nginx Startup Nginx -Verifizierung Nginx Is Nginx Start Erkunden
