Heim Betrieb und Instandhaltung Betrieb und Wartung von Linux Beispielcode-Analyse für Linux-Multithread-Programmierung

Beispielcode-Analyse für Linux-Multithread-Programmierung

May 26, 2023 pm 10:04 PM
linux

Nehmen wir zunächst ein Beispiel. Wir erstellen zwei Threads, um eine Zahl zu erhöhen. Vielleicht hat dieses Beispiel keinen praktischen Wert, aber mit einer kleinen Änderung können wir es an anderen Stellen verwenden.

Code:

/*thread_example.c : c multiple thread programming in linux
 *author : falcon
 *e-mail : tunzhj03@st.lzu.edu.cn
 */
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define max 10

pthread_t thread[2];
pthread_mutex_t mut;
int number=0, i;

void *thread1()
{
    printf ("thread1 : i&#39;m thread 1/n");

    for (i = 0; i < max; i++)
    {
        printf("thread1 : number = %d/n",number);
        pthread_mutex_lock(&mut);
            number++;
        pthread_mutex_unlock(&mut);
        sleep(2);
    }


    printf("thread1 :主函数在等我完成任务吗?/n");
    pthread_exit(null);
}

void *thread2()
{
    printf("thread2 : i&#39;m thread 2/n");

    for (i = 0; i < max; i++)
    {
        printf("thread2 : number = %d/n",number);
        pthread_mutex_lock(&mut);
            number++;
        pthread_mutex_unlock(&mut);
        sleep(3);
    }


    printf("thread2 :主函数在等我完成任务吗?/n");
    pthread_exit(null);
}

void thread_create(void)
{
    int temp;
    memset(&thread, 0, sizeof(thread));     //comment1
    /*创建线程*/
    if((temp = pthread_create(&thread[0], null, thread1, null)) != 0) //comment2   
        printf("线程1创建失败!/n");
    else
        printf("线程1被创建/n");

    if((temp = pthread_create(&thread[1], null, thread2, null)) != 0) //comment3
        printf("线程2创建失败");
    else
        printf("线程2被创建/n");
}

void thread_wait(void)
{
    /*等待线程结束*/
    if(thread[0] !=0)      {       //comment4          pthread_join(thread[0],null);
        printf("线程1已经结束/n");
     }
    if(thread[1] !=0)      {         //comment5        pthread_join(thread[1],null);
        printf("线程2已经结束/n");
     }
}

int main()
{
    /*用默认属性初始化互斥锁*/
    pthread_mutex_init(&mut,null);

    printf("我是主函数哦,我正在创建线程,呵呵/n");
    thread_create();
    printf("我是主函数哦,我正在等待线程完成任务阿,呵呵/n");
    thread_wait();

    return 0;
}
Nach dem Login kopieren

Lass es uns zuerst kompilieren und ausführen

Zitat:

falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c
falcon@falcon:~/program/c/code/ftp$ ./thread_example
我是主函数哦,我正在创建线程,呵呵
线程1被创建
线程2被创建
我是主函数哦,我正在等待线程完成任务阿,呵呵
thread1 : i&#39;m thread 1
thread1 : number = 0
thread2 : i&#39;m thread 2
thread2 : number = 1
thread1 : number = 2
thread2 : number = 3
thread1 : number = 4
thread2 : number = 5
thread1 : number = 6
thread1 : number = 7
thread2 : number = 8
thread1 : number = 9
thread2 : number = 10
thread1 :主函数在等我完成任务吗?
线程1已经结束
thread2 :主函数在等我完成任务吗?
线程2已经结束
Nach dem Login kopieren

Die Kommentare im Beispielcode sollten jetzt klarer sein.

Zitat:

Thread-bezogene Vorgänge

一 pthread_t

pthread_t ist in der Header-Datei /usr/include/bits/pthreadtypes.h definiert:
 typedef unsigned long int pthread_t;
 Es ist die Kennung eines Threads.

Zweiter pthread_create

Die Funktion pthread_create wird zum Erstellen eines Threads verwendet. Sein Prototyp ist:
 extern int pthread_create __p ((pthread_t *__thread, __const pthread_attr_t *__attr,
 void *(*__start_routine) (void *), void * __arg ));
Der erste Parameter ist ein Zeiger auf die Thread-ID, der zweite Parameter wird zum Festlegen der Thread-Attribute verwendet, der dritte Parameter ist die Startadresse der Thread-Ausführungsfunktion und der letzte Parameter ist der Parameter der Ausführung Funktion. Hier benötigt unser Funktionsthread keine Parameter, daher wird der letzte Parameter auf einen Nullzeiger gesetzt. Wir setzen außerdem den zweiten Parameter auf einen Nullzeiger, wodurch ein Thread mit Standardattributen generiert wird. Das Setzen und Ändern von Thread-Attributen erklären wir im nächsten Abschnitt. Wenn der Thread erfolgreich erstellt wurde, gibt die Funktion 0 zurück. Wenn er nicht 0 ist, schlägt die Thread-Erstellung fehl. Häufige Fehlerrückgabecodes sind eagain und einval. Ersteres bedeutet, dass das System beispielsweise die Erstellung neuer Threads einschränkt, wenn die Anzahl der Threads zu groß ist. Letzteres bedeutet, dass der durch den zweiten Parameter dargestellte Thread-Attributwert unzulässig ist. Nachdem der Thread erfolgreich erstellt wurde, führt der neu erstellte Thread die durch Parameter drei und Parameter vier bestimmte Funktion aus, und der ursprüngliche Thread führt weiterhin die nächste Codezeile aus.

Drei pthread_join pthread_exit
 
Die Funktion pthread_join wird verwendet, um auf das Ende eines Threads zu warten. Der Funktionsprototyp lautet:
 extern int pthread_join __p ((pthread_t __th, void **__thread_return));
 Der erste Parameter ist die Thread-ID, auf die gewartet werden soll, und der zweite Parameter ist ein benutzerdefinierter Zeiger, der verwendet werden kann zu speichern Der Rückgabewert des erwarteten Threads. Diese Funktion ist eine Thread-blockierende Funktion. Die aufrufende Funktion wartet, bis der wartende Thread endet. Wenn die Funktion zurückkehrt, werden die Ressourcen des wartenden Threads wiederhergestellt. Es gibt zwei Möglichkeiten, einen Thread zu beenden: Wenn die Funktion endet, endet auch der Thread, der sie aufgerufen hat. Die andere Möglichkeit ist die Funktion pthread_exit. Sein Funktionsprototyp ist:
extern void pthread_exit __p ((void *__retval)) __attribute__ ((__noreturn__));
Der einzige Parameter ist der Rückkehrcode der Funktion, solange der zweite Parameter thread_return in pthread_join nicht null ist Der Wert wird an thread_return übergeben. Als letztes ist zu beachten, dass nicht mehrere Threads auf einen Thread warten können. Andernfalls kehrt der erste Thread, der das Signal empfängt, erfolgreich zurück und die verbleibenden Threads, die pthread_join aufrufen, geben den Fehlercode esrch zurück.
 In diesem Abschnitt haben wir den einfachsten Thread geschrieben und die drei am häufigsten verwendeten Funktionen beherrscht: pthread_create, pthread_join und pthread_exit. Schauen wir uns als Nächstes einige allgemeine Eigenschaften von Threads an und wie man sie festlegt.

Mutex-Sperre im Zusammenhang

Mutex-Sperre wird verwendet, um sicherzustellen, dass innerhalb eines bestimmten Zeitraums nur ein Thread einen Code ausführt.

一 pthread_mutex_init

Die Funktion pthread_mutex_init wird verwendet, um eine Mutex-Sperre zu generieren. Der Nullparameter gibt an, dass die Standardeigenschaften verwendet werden. Wenn Sie einen Mutex für ein bestimmtes Attribut deklarieren müssen, müssen Sie die Funktion pthread_mutexattr_init aufrufen. Die Funktion pthread_mutexattr_setpshared und die Funktion pthread_mutexattr_settype werden zum Festlegen der Mutex-Sperrattribute verwendet. Die vorherige Funktion legt das Attribut pshared fest, das zwei Werte hat: pthread_process_private und pthread_process_shared. Ersteres wird verwendet, um Threads in verschiedenen Prozessen zu synchronisieren, und letzteres wird verwendet, um verschiedene Threads in diesem Prozess zu synchronisieren. Im obigen Beispiel verwenden wir das Standardattribut pthread_process_private. Letzteres wird verwendet, um den Mutex-Sperrtyp festzulegen. Die optionalen Typen sind pthread_mutex_normal, pthread_mutex_errorcheck, pthread_mutex_recursive und pthread_mutex_default. Sie definieren jeweils unterschiedliche Auflistungs- und Entsperrmechanismen. Unter normalen Umständen wird das letzte Standardattribut ausgewählt.

Zwei pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

Die pthread_mutex_lock-Anweisung beginnt mit der Sperre mit einer Mutex-Sperre. Der nachfolgende Code wird gesperrt, bis pthread_mutex_unlock aufgerufen wird, dh er kann nur von einem Thread gleichzeitig aufgerufen und ausgeführt werden. Wenn ein Thread pthread_mutex_lock ausführt und die Sperre zu diesem Zeitpunkt von einem anderen Thread verwendet wird, wird der Thread blockiert, dh das Programm wartet, bis ein anderer Thread die Mutex-Sperre aufhebt.

Hinweis:

1 Es ist zu beachten, dass die beiden oben genannten Ruhezustände nicht nur zu Demonstrationszwecken dienen, sondern auch dazu dienen, dem Thread eine gewisse Zeit lang den Ruhezustand zu ermöglichen, sodass der Thread die Mutex-Sperre aufheben und darauf warten kann, dass ein anderer Thread diese Sperre verwendet. Dieses Problem wird in Referenz 1 unten erläutert. Allerdings scheint es unter Linux keine pthread_delay_np-Funktion zu geben (ich habe es versucht und es wurde mir angezeigt, dass kein Verweis auf die definierte Funktion vorhanden ist), daher habe ich stattdessen Sleep verwendet. In Referenz 2 wird jedoch eine andere Methode angegeben, die dies zu tun scheint durch pthread_cond_timedwait ersetzt werden, was eine Möglichkeit bietet, dies zu erreichen.

2 Bitte beachten Sie die Kommentare 1-5 darin. Das ist das Problem, das ich mehrere Stunden lang herausgefunden habe.
Wenn Kommentar1, Kommentar4 und Kommentar5 nicht vorhanden sind, führt dies zu einem Segfault während pthread_join. Darüber hinaus sind die oben genannten Kommentare2 und Kommentar3 die Hauptursache. Denken Sie also daran, den gesamten Code zu schreiben. Da der obige Thread möglicherweise nicht erfolgreich erstellt werden kann, ist es unmöglich, auf das Ende dieses Threads zu warten, und bei Verwendung von pthread_join tritt ein Segmentierungsfehler auf (auf einen unbekannten Speicherbereich wird zugegriffen). Wenn Sie Memset verwenden, müssen Sie außerdem die Header-Datei string.h einbinden

Das obige ist der detaillierte Inhalt vonBeispielcode-Analyse für Linux-Multithread-Programmierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Unterschied zwischen CentOS und Ubuntu Unterschied zwischen CentOS und Ubuntu Apr 14, 2025 pm 09:09 PM

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)

CentOS 'Wahl nach der Beendigung der Wartung CentOS 'Wahl nach der Beendigung der Wartung Apr 14, 2025 pm 08:51 PM

CentOS wurde eingestellt, Alternativen umfassen: 1. Rocky Linux (beste Kompatibilität); 2. Almalinux (kompatibel mit CentOS); 3. Ubuntu Server (Konfiguration erforderlich); 4. Red Hat Enterprise Linux (kommerzielle Version, bezahlte Lizenz); 5. Oracle Linux (kompatibel mit CentOS und RHEL). Bei der Migration sind Überlegungen: Kompatibilität, Verfügbarkeit, Unterstützung, Kosten und Unterstützung in der Gemeinde.

So installieren Sie CentOs So installieren Sie CentOs Apr 14, 2025 pm 09:03 PM

CentOS -Installationsschritte: Laden Sie das ISO -Bild herunter und verbrennen Sie bootfähige Medien. Starten und wählen Sie die Installationsquelle; Wählen Sie das Layout der Sprache und Tastatur aus. Konfigurieren Sie das Netzwerk; Partition die Festplatte; Setzen Sie die Systemuhr; Erstellen Sie den Root -Benutzer; Wählen Sie das Softwarepaket aus; Starten Sie die Installation; Starten Sie nach Abschluss der Installation von der Festplatte neu und starten Sie von der Festplatte.

So verwenden Sie Docker Desktop So verwenden Sie Docker Desktop Apr 15, 2025 am 11:45 AM

Wie benutze ich Docker Desktop? Docker Desktop ist ein Werkzeug zum Ausführen von Docker -Containern auf lokalen Maschinen. Zu den zu verwendenden Schritten gehören: 1.. Docker Desktop installieren; 2. Start Docker Desktop; 3.. Erstellen Sie das Docker -Bild (mit Dockerfile); 4. Build Docker Image (mit Docker Build); 5. Docker -Container ausführen (mit Docker Run).

Detaillierte Erklärung des Docker -Prinzips Detaillierte Erklärung des Docker -Prinzips Apr 14, 2025 pm 11:57 PM

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.

Welche Computerkonfiguration ist für VSCODE erforderlich? Welche Computerkonfiguration ist für VSCODE erforderlich? Apr 15, 2025 pm 09:48 PM

VS Code system requirements: Operating system: Windows 10 and above, macOS 10.12 and above, Linux distribution processor: minimum 1.6 GHz, recommended 2.0 GHz and above memory: minimum 512 MB, recommended 4 GB and above storage space: minimum 250 MB, recommended 1 GB and above other requirements: stable network connection, Xorg/Wayland (Linux)

So sehen Sie den Docker -Prozess So sehen Sie den Docker -Prozess Apr 15, 2025 am 11:48 AM

Docker Process Viewing -Methode: 1. Docker Cli -Befehl: Docker PS; 2. SYSTEMD CLI -Befehl: SystemCTL Status Docker; 3.. Docker Compose CLI Command: Docker-Compose PS; 4. Process Explorer (Windows); 5. /proc -Verzeichnis (Linux).

Was tun, wenn das Docker -Bild fehlschlägt? Was tun, wenn das Docker -Bild fehlschlägt? Apr 15, 2025 am 11:21 AM

Fehlerbehebung Schritte für fehlgeschlagene Docker -Bild Build: Überprüfen Sie die Dockerfile -Syntax und die Abhängigkeitsversion. Überprüfen Sie, ob der Build -Kontext den erforderlichen Quellcode und die erforderlichen Abhängigkeiten enthält. Sehen Sie sich das Build -Protokoll für Fehlerdetails an. Verwenden Sie die Option -Target -Option, um eine hierarchische Phase zu erstellen, um Fehlerpunkte zu identifizieren. Verwenden Sie die neueste Version von Docker Engine. Erstellen Sie das Bild mit--t [Bildname]: Debugg-Modus, um das Problem zu debuggen. Überprüfen Sie den Speicherplatz und stellen Sie sicher, dass dies ausreicht. Deaktivieren Sie Selinux, um eine Störung des Build -Prozesses zu verhindern. Fragen Sie Community -Plattformen um Hilfe, stellen Sie Dockerfiles an und erstellen Sie Protokollbeschreibungen für genauere Vorschläge.

See all articles