Wie lässt man den Hauptthread warten, bis alle untergeordneten Threads beendet sind?

Lesezeit: 7 Minuten

Ich beabsichtige, 2 Threads im Haupt-Thread zu feuern, und der Haupt-Thread sollte warten, bis alle 2 untergeordneten Threads fertig sind, so mache ich es.

void *routine(void *arg)
{
    sleep(3);
}

int main()
{
    for (int i = 0; i < 2; i++) {
        pthread_t tid;
        pthread_create(&tid, NULL, routine, NULL);
        pthread_join(&tid, NULL);  //This function will block main thread, right?
    }
}

Im obigen Code, pthread_join In der Tat lässt der Hauptthread auf die untergeordneten Threads warten, aber das Problem ist, dass der zweite Thread nicht erstellt wird, bis der erste fertig ist. Das ist nicht das, was ich will.

Was ich möchte, ist, dass die 2 Threads sofort im Hauptthread erstellt werden und der Hauptthread dann darauf wartet, dass sie beendet werden. Sieht aus als ob pthread_join kann den trick nicht machen, oder?

Ich dachte, vielleicht über a semaphore Ich kann den Job machen, aber anders?

  • Bewahren Sie die Fäden in einem Behälter auf und verbinden Sie sie dann mit jedem von ihnen nach du erschaffst sie alle.

    – James McNellis

    24. Juli 2012 um 5:17 Uhr

  • Funktioniert nicht so gut, wenn einer davon fertig ist, bevor alle erstellt sind?

    – mckenzm

    20. Januar 2021 um 1:48 Uhr

Benutzeravatar von perreal
perreal

int main()
{
    pthread_t tid[2];
    for (int i = 0; i < 2; i++) {
        pthread_create(&tid[i], NULL, routine, NULL);
    }
    for (int i = 0; i < 2; i++)
       pthread_join(tid[i], NULL);
    return 0;
}

  • Wie machen wir das unter Windows? @Perreal

    – Turmuka

    7. Oktober 2017 um 14:47 Uhr

  • Ich weiß, dass dies weit zurückreicht, aber ich möchte etwas fragen. Threads könnten genau dann ausgelöst werden, wenn die pthread_create zurückgibt, würde dies keine Probleme verursachen, wenn die Threads erstellt und beendet werden, bevor sie verbunden werden?

    – Tortellini Dienstag

    21. September 2020 um 13:39 Uhr

  • Ich verstehe Ihre Bedenken nicht ganz, aber lesen Sie bitte das Dokument für die Join-Funktion. Es wartet auf den Thread, wenn der Thread ausgeführt wird oder gerade zurückkehrt.

    – perreal

    21. September 2020 um 13:44 Uhr

  • Soweit ich weiß, funktioniert dieser Code möglicherweise nicht. Das pthread_join Funktion würde den “Haupt-Thread” aussetzen, bis Thread A seine Ausführung beendet hat, das Problem ist, dass Thread B in dieser Zeit beendet sein könnte, also der nächste Aufruf an pthread_join undefiniertes Verhalten erzeugen würde.

    – Herr Dave1999

    18. Januar 2021 um 16:00 Uhr

  • Hier kommt der Join-Aufruf von einem einzelnen Thread, den die Leute gerne als Haupt-Thread bezeichnen. Dein Zitat trifft also nicht zu. Wenn Sie pthread_join von mehreren Threads aufrufen, wäre dies eine andere Geschichte. Beachten Sie, dass keiner der gespawnten Laufflächen über die hinaus leben wird routine.

    – perreal

    18. Januar 2021 um 17:48 Uhr


Benutzeravatar von Basile Starynkevitch
Basile Starynkevitch

Erstellen Sie zuerst alle Threads und treten Sie dann allen bei:

pthread_t tid[2];

/// create all threads
for (int i = 0; i < 2; i++) {
    pthread_create(&tid[i], NULL, routine, NULL);
}

/// wait all threads by joining them
for (int i = 0; i < 2; i++) {
    pthread_join(tid[i], NULL);  
}

Alternativ haben einige pthread_attr_t variabel, verwenden pthread_attr_init(3) dann pthread_attr_setdetachedstate(3)
darauf, dann übergeben Sie seine Adresse an pthread_create(3) zweites Argument. Thos würde die Threads in erstellen losgelöst Zustand. Oder verwenden pthread_detach wie in Jxhs Antwort erklärt.

Denken Sie daran, etwas Gutes zu lesen Pthread-Tutorial. Möglicherweise möchten Sie Mutexe und Bedingungsvariablen verwenden.

Sie könnten Frameworks verwenden, die sie umhüllen, z Qt oder POCO (in C++), oder lesen Sie ein gutes C++-Buch und verwenden C++-Threads.

Konzeptionell haben Threads jeweils ihre eigenen Call-Stack und verwandt sind Fortsetzungen. Sie sind schwer”.

Betrachten Sie einige Agentenorientierte Programmierung Ansatz: Als Faustregel sollten Sie nicht viele Threads haben (z. B. 20 Threads auf einer 10-Kern-Prozessor ist vernünftig, 200 Threads werden es nicht sein, es sei denn, viele von ihnen schlafen oder warten) und und und möchten, dass Threads mit Mutex und synchronisiert werden Bedingungsvariablen und ziemlich oft (mehrmals pro Sekunde) mit anderen Threads kommunizieren und/oder synchronisieren. Siehe auch Umfrage(2), fifo(7), Unix(7), sem_overview(7) mit shm_overview(7) als eine andere Art der Kommunikation zwischen Threads. Vermeiden Sie im Allgemeinen die Verwendung Signal(7) mit Fäden (lesen Signalsicherheit(7)…) und verwenden öffnen(3) mit Vorsicht (wahrscheinlich nur im Hauptthread).

Ein pragmatischer Ansatz wäre, die meisten Ihrer Threads einige auszuführen Ereignisschleife (unter Verwendung Umfrage(2), pauswählen(2)vielleicht eventfd(2), signalfd(2)….), vielleicht kommunizieren mit Rohr(7) oder Unix(7) Steckdosen. Siehe auch Steckdose(7).

Vergessen Sie nicht, die Kommunikationsprotokolle zwischen Threads (auf Papier) zu dokumentieren. Für einen theoretischen Ansatz lesen Sie Bücher über π-Kalkül und bewusst sein Satz von Rice : Das Debuggen gleichzeitiger Programme ist schwierig.

  • Das Hauptproblem dabei ist, dass pthread_join() blockiert. Wenn Sie also 512 Threads haben, die jeweils 10 Stunden lang +/- 5 Stunden laufen, werden die Threads 1-511 nicht verbunden, bis Thread 0 abgeschlossen ist. Und einer davon kann viel früher enden. Ich bin mir auch nicht sicher, ob es in vielen Fällen sinnvoll ist, sie zu lösen. Wenn die Zeiten mehr oder weniger konstant wären, könnten wir die Erstellung mit einer Verzögerung von beispielsweise 2 Minuten verschieben.

    – mckenzm

    20. Januar 2021 um 2:00 Uhr

Benutzeravatar von jxh
jxh

Sie könnten die Threads losgelöst beginnen und müssen sich keine Gedanken über den Beitritt machen.

for (int i = 0; i < 2; i++) {
    pthread_t tid;
    pthread_create(&tid, NULL, routine, NULL);
    pthread_detach(tid);
}
pthread_exit(0);

Alternativ können Sie den Thread, der stirbt, an den Haupt-Thread zurückmelden lassen, wer er ist, sodass die Threads in der Reihenfolge, in der sie beendet wurden, zusammengeführt werden, und nicht in der Reihenfolge, in der Sie sie erstellt haben.

void *routine(void *arg)
{
    int *fds = (int *)arg;
    pthread_t t = pthread_self();
    usleep((rand()/(1.0 + RAND_MAX)) * 1000000);
    write(fds[1], &t, sizeof
}

int main()
{
    int fds[2];
    srand(time(0));
    pipe(fds);
    for (int i = 0; i < 2; i++) {
        pthread_t tid;
        pthread_create(&tid, NULL, routine, fds);
        printf("created: %llu\n", (unsigned long long)tid);
    }
    for (int i = 0; i < 2; i++) {
        pthread_t tid;
        read(fds[0], &tid, sizeof(tid));
        printf("joining: %llu\n", (unsigned long long)tid);
        pthread_join(tid, 0);
    }
    pthread_exit(0);
}

  • Ich weiß, das ist sehr spät, aber müssen Sie nicht die fds von der Pipe schließen?

    – sgupta

    20. Juli 2016 um 4:11 Uhr

  • @ user1075375 Nein. Es reicht aus, den Prozess zu beenden.

    – jxh

    20. Juli 2016 um 5:50 Uhr

  • Ja, aber jemand könnte diesen Beispielcode in einem Prozess verwenden, der nicht beendet wird, sobald die Worker-Threads beendet werden. Na ja, zu schade für sie, dass sie nicht wissen, wie sie ihre FDS befreien können.

    – sgupta

    20. Juli 2016 um 16:48 Uhr

  • @user1075375 Wenn der Prozess nicht beendet wird, sollte die Pipe für zukünftige Threads offen gelassen werden.

    – jxh

    20. Juli 2016 um 16:57 Uhr

  • tbh, das ist ein bisschen so, als würde man sagen, dass Mallocs in main nicht freigegeben werden sollten, weil sie wiederverwendet werden können. Wenn später erzeugte Threads diese fds nicht verwenden, verschwenden Sie nur eine Ressource, die auf den meisten Systemen knapper ist als Speicher.

    – sgupta

    20. Juli 2016 um 20:35 Uhr

Benutzeravatar von Dilip Dabhade
Dilip Dabhade

#include<stdio.h>
#include<pthread.h>

int icnt = 0;   //in non_bss data segment
pthread_mutex_t lock;     //lock variable created stored into bss data segment


void *Thread_count(void* args)      //syncronization 
{
pthread_mutex_lock(&lock);              //lock aquire 
    
icnt++;

for(int x = 1; x <= icnt; x++)
{
    printf("Hello from Thread_count : %d \n",icnt);
}
printf("\n");

pthread_mutex_unlock(&lock);            //release lock  
pthread_exit(NULL);                     //exit from child thread
}


int main()
{

pthread_t threads[4];  //created array of {unsigned long int}
int status = 0;

//creating threads in loop      
for(int i = 1; i <= sizeof(threads)/sizeof(threads[0]); i++)
{
    pthread_create(&threads[i], NULL, &Thread_count, NULL);
}

//waiting for threads in loop
for(int j = 1; j <= sizeof(threads)/sizeof(threads[0]); j++)
{
    pthread_join(threads[j], &status);
    
    printf("Thread number : %d     <-->  Thread status : %d\n",j, status);
}


pthread_exit(0);  //end of main thread
}

1402520cookie-checkWie lässt man den Hauptthread warten, bis alle untergeordneten Threads beendet sind?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy