Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> C Taal

C++ Multithreading beheersen: Efficiënt gelijktijdig programmeren

Wat is multithreading?

Multithreading is een gespecialiseerde vorm van multitasking. Multitasking is de eigenschap die uw computer in staat stelt om twee of meer programma's gelijktijdig uit te voeren. In het algemeen zijn er twee soorten multitasking: proces-gebaseerd en thread-gebaseerd.

Proces-gebaseerde multitasking beheert de gelijktijdige uitvoering van programma's. Thread-gebaseerde multitasking houdt zich bezig met de gelijktijdige uitvoering van onderdelen van hetzelfde programma.

Een multithreaded programma bevat twee of meer delen die gelijktijdig kunnen draaien. Elk deel heet een thread en definieert een afzonderlijk uitvoeringspad.

C++ bevat geen ingebouwde ondersteuning voor multithreaded applicaties. In plaats daarvan steunt het volledig op het besturingssysteem voor deze functionaliteit.

Deze tutorial gaat ervan uit dat u werkt op Linux OS en we schrijven een multithreaded C++-programma met POSIX. POSIX Threads (Pthreads) biedt API's die beschikbaar zijn op veel Unix-achtige systemen zoals FreeBSD, NetBSD, GNU/Linux, Mac OS X en Solaris.

Threads aanmaken

De volgende routine wordt gebruikt om een POSIX-thread aan te maken:

#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)

pthread_create creëert een nieuwe thread en maakt deze uitvoerbaar. De parameters zijn:

Nr. Parameter & Beschrijving
1

thread

Een unieke, opake identifier voor de nieuwe thread, teruggegeven door de subroutine.

2

attr

Een opake attribuutobject dat gebruikt kan worden om threadeigenschappen in te stellen. U kunt NULL doorgeven voor standaardwaarden.

3

start_routine

De C++-routine die de thread zal uitvoeren zodra deze is aangemaakt.

4

arg

Een enkel argument dat aan start_routine kan worden doorgegeven. Moet per referentie als een void-pointer worden doorgegeven. NULL mag gebruikt worden als geen argument nodig is.

Het maximum aantal threads dat een proces kan aanmaken is implementatie-afhankelijk. Eenmaal aangemaakt, zijn threads peers en kunnen ze andere threads aanmaken. Er is geen impliciete hiërarchie of afhankelijkheid.

Threads beëindigen

De volgende routine gebruiken we om een POSIX-thread te beëindigen:

#include <pthread.h>
pthread_exit (status)

pthread_exit wordt gebruikt om een thread expliciet te beëindigen. Meestal wordt pthread_exit() aangeroepen nadat een thread zijn werk heeft voltooid en niet meer hoeft te bestaan.

Als main() klaar is voordat de door hem aangemaakte threads, en afsluit met pthread_exit(), zullen de andere threads doorgaan met uitvoeren. Anders worden ze automatisch beëindigd wanneer main() afloopt.

Voorbeeld

Dit eenvoudige voorbeeld creëert 5 threads met pthread_create(). Elke thread print "Hello World!" en beëindigt met pthread_exit().

#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;

#define NUM_THREADS 5

void *PrintHello(void *threadid) {
    long tid = (long)threadid;
    cout << "Hello World! Thread ID, " << tid << endl;
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    int rc, i;
    for(i = 0; i < NUM_THREADS; i++) {
        cout << "main() : creating thread, " << i << endl;
        rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
        if (rc) {
            cout << "Error: unable to create thread," << rc << endl;
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

Compileer met de -lpthread bibliotheek:

$ gcc test.cpp -lpthread

Uitvoer:

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4

Argumenten doorgeven aan threads

Dit voorbeeld laat zien hoe u meerdere argumenten via een structuur kunt doorgeven. U kunt elk datatype doorgeven omdat de callback naar void wijst.

#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;

#define NUM_THREADS 5

struct thread_data {
    int thread_id;
    char *message;
};

void *PrintHello(void *threadarg) {
    struct thread_data *my_data = (struct thread_data *) threadarg;
    cout << "Thread ID : " << my_data->thread_id;
    cout << " Message : " << my_data->message << endl;
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[NUM_THREADS];
    struct thread_data td[NUM_THREADS];
    int rc, i;
    for(i = 0; i < NUM_THREADS; i++) {
        cout << "main() : creating thread, " << i << endl;
        td[i].thread_id = i;
        td[i].message = "This is message";
        rc = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]);
        if (rc) {
            cout << "Error: unable to create thread," << rc << endl;
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

Uitvoer (volgorde kan variëren):

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message

Threads joinen en detachen

Er zijn twee routines om threads te joinen of te detachen:

pthread_join (threadid, status)
pthread_detach (threadid)

pthread_join() blokkeert de aanroepende thread totdat de gespecificeerde thread beëindigd is. Alleen threads die als joinable zijn aangemaakt, kunnen gejoind worden. Een thread die als detached is aangemaakt, kan nooit gejoind worden.

Voorbeeld: wachten op thread-voltooiing met pthread_join

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
using namespace std;

#define NUM_THREADS 5

void *wait(void *t) {
    long tid = (long)t;
    sleep(1);
    cout << "Sleeping in thread " << endl;
    cout << "Thread with id : " << tid << " ...exiting " << endl;
    pthread_exit(NULL);
}

int main() {
    int rc, i;
    pthread_t threads[NUM_THREADS];
    pthread_attr_t attr;
    void *status;

    // Initialiseer en stel thread in als joinable
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for(i = 0; i < NUM_THREADS; i++) {
        cout << "main() : creating thread, " << i << endl;
        rc = pthread_create(&threads[i], &attr, wait, (void *)i);
        if (rc) {
            cout << "Error: unable to create thread," << rc << endl;
            exit(-1);
        }
    }

    // Vrijgeven attributen en wachten op threads
    pthread_attr_destroy(&attr);
    for(i = 0; i < NUM_THREADS; i++) {
        rc = pthread_join(threads[i], &status);
        if (rc) {
            cout << "Error: unable to join," << rc << endl;
            exit(-1);
        }
        cout << "Main: completed thread id :" << i;
        cout << " exiting with status :" << status << endl;
    }
    cout << "Main: program exiting." << endl;
    pthread_exit(NULL);
}

Uitvoer:

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0 exiting with status :0
Main: completed thread id :1 exiting with status :0
Main: completed thread id :2 exiting with status :0
Main: completed thread id :3 exiting with status :0
Main: completed thread id :4 exiting with status :0
Main: program exiting.

C Taal

  1. C++ operators: complete gids met praktische voorbeelden
  2. C++ comments: best practices voor leesbare, onderhoudbare code
  3. C++ Class Templates Beheersen: Een Praktische Gids
  4. C++ Programmeertaal: Overzicht & Belangrijkste Kenmerken
  5. C++ Constanten & Literals Uitgelegd: Types, Syntax en Best Practices
  6. Uitgebreide Gids voor C++ Operators: Types, Gebruik en Best Practices
  7. Numerieke Typen in C++ Beheersen: Een Praktische Gids
  8. C++ Referenties Begrijpen: Sleutelconcepten & Verschillen met Pointers
  9. C++ Templates Beheersen: Gids voor Generisch Programmeren
  10. C++ Multithreading beheersen: Efficiënt gelijktijdig programmeren
  11. C# Multithreading Beheersen: Prestaties en Efficiëntie Verhogen