Funzione pThread_Join in lingua C con esempi di thread singoli e multipli

Funzione pThread_Join in lingua C con esempi di thread singoli e multipli
La lingua C offre la possibilità di sviluppare i programmi multitasking utilizzando la libreria PThread dello standard POSIX. Questo metodo aumenta la velocità del programma finito eseguendo più thread in parallelo con la funzione principale.

Per creare un programma di successo utilizzando questo metodo di programmazione, è necessario fare alcune considerazioni speciali. Ad esempio, se i tempi di esecuzione di un thread sono più lunghi di quelli della funzione principale () ed è completamente eseguito, il programma terminerà e quindi tutti i thread associati, sia che abbiano completato il loro compito o no.

Ciò può causare problemi critici perché un thread che termina inaspettatamente potrebbe essere in procinto di salvare un dati generato dall'utente, scrivere su un file o un dispositivo o eseguire qualche altro compito importante.

In questo articolo di Linux, imparerai come utilizzare la funzione pThread_join () per garantire che uno o più thread siano terminati in modo affidabile prima che un programma esca o riprenda.

Sintassi della funzione pThread_join () in lingua C

int pThread_Join (thread pThread_t, void ** retval);

Descrizione della funzione pThread_Join () in lingua C

La funzione pThread_join () attende il processo da cui viene chiamato fino a quando un thread non ha terminato il suo compito. Questa funzione sospende la funzione da cui viene chiamata fino a quando il sub-process specificato dal suo identificatore nell'argomento di input del thread termina.

Una volta che il thread termina il suo compito, il programma riprende l'esecuzione dalla riga successiva del codice che chiama pThread_join ().

Quando il sub-process termina, la funzione pThread_join () restituisce lo stato di uscita del thread nell'argomento retval.

Successivamente, vediamo gli argomenti di input a pThread_Join () insieme a una descrizione della funzione che soddisfa ciascuno di questi argomenti:

filo: Questo argomento di input è un valore di dati del tipo pThread_t ed è l'identificatore del sottoprocesso che la funzione pThread_join () dovrebbe aspettarsi.

Il valore dell'identificatore viene generato dal sistema e viene ottenuto a seguito della funzione pThread_create () nel thread dell'argomento di output quando viene creato il thread.

Retval: Questo argomento di input è un puntatore a (void *) in cui la funzione pThread_join () memorizza lo stato di uscita del thread.

Se pThread_Join () restituisce correttamente, restituisce 0 come risultato. Se si verifica un errore, questa funzione restituisce un numero intero con un valore che rappresenta l'errore che si è verificato. Più tardi, vedrai una sezione speciale che descrive tutti gli errori che questa funzione può generare e come identificarli.

La funzione pThread_join () è definita nella pThread.HEADER H. Per usarlo, le seguenti intestazioni devono essere incluse in ".File C ", come mostrato nel seguente:

#includere
#includere

Nota: è importante utilizzare questa funzione solo quando necessario, poiché è possibile estendere il tempo di esecuzione di un programma interrompendo un processo per attendere che l'altro.

Errori di compilazione nei programmi con thread

Quando si compilano i programmi GCC che utilizzano i thread, la compilation potrebbe fallire se non viene eseguita correttamente dalla riga di comando.

Il messaggio di errore più comune che viene emesso dal compilatore afferma che una delle funzioni del thread a cui ci riferiamo nel codice non è definita.

Questi errori spesso comportano uno spreco di tempo prezioso nel controllare le intestazioni che abbiamo inserito nel codice, la loro integrità e le directory associate al compilatore poiché tutto indica che il problema è lì.

Sebbene le funzioni che causano l'errore siano definite nella "Pthread.H ”” e sono inclusi nel codice, il compilatore non riconosce queste funzioni a meno che la libreria PThread non venga chiamata dalla riga di comando durante la compilation.

Nella seguente illustrazione, è possibile vedere il modo corretto di chiamare la libreria PThread (evidenziata in verde) dalla console di comando durante la compilazione di programmi con thread:

~ $ GCC -PThread Path/FileName.c -o out_name

Come possiamo vedere nella figura seguente, l'errore scompare quando la libreria PThread viene chiamata durante la compilazione.

Come utilizzare la funzione pThread_join () per attendere un thread per completare l'esecuzione nella lingua C

In questo esempio, creiamo un thread che ha un tempo di esecuzione più lungo rispetto alla funzione principale (). Dopo aver creato il thread, utilizziamo pThread_join () per attendere l'intera esecuzione del thread prima di uscire dalla funzione principale () e terminare il programma.

A tale scopo, creiamo la funzione thread_f () che esegue il thread. Questa funzione è un ciclo "per" con 5 cicli di una seconda durata, ognuno dei quali stampica il "Secondi fino alla fine del thread:"Messaggio, seguito dal numero di secondi rimanenti nella console di comando.

Dalla funzione principale (), creiamo la thread_1 con la funzione pThread_create (). Quindi, chiamiamo la funzione pThread_join () per attendere che il sottoprocesso completi l'esecuzione prima di uscire dal programma.

La chiamata di funzione pThread_join () va con l'identificatore thread_1 come primo argomento di input e il retval come null nel secondo argomento. Vediamo il seguente codice completo per questo esempio:

#includere
#includere
#includere
#includere
void* thread_f (void* n);
int main ()

pThread_t thread_1;
pThread_create (& thread_1, null, thread_f, null);
pThread_Join (thread_1, null);
restituzione 0;

void* thread_f (void* n)

per (int a = 5; a!= 0; UN--)

printf ("Seconds to End of Thread: %i \ n", a);
sonno (1);

printf ("fine del thread \ n");
pThread_exit (N);

La seguente immagine mostra la compilazione e l'esecuzione di questo codice:

Come abbiamo visto nella figura, il loop "per" ha completato i suoi 5 cicli e il programma è chiuso dopo che Thread_1 ha terminato la sua esecuzione. Vediamo cosa succede se rimuoviamo la funzione pThread_join (). Compilare ed eseguire il seguente codice:

Come possiamo vedere nella figura, il ciclo "per" di thread_1 non è stato in grado di completare un passaggio prima che la funzione principale () sia completamente eseguita e il programma viene terminato.

Come utilizzare la funzione pThread_join () per attendere un thread multiplo per completare l'esecuzione nella lingua C

In questo esempio, ti mostreremo come utilizzare la funzione pThread_join () per attendere il completamento di più thread simultanei.

Per fare ciò, utilizziamo il codice dall'esempio precedente e aggiungiamo un secondo thread che è thread_2 e una seconda routine che è thread_f_2 () che esegue in parallelo con thread_1. Il tempo di esecuzione di questa routine è due volte più lungo di quello di thread_f_1 () che richiede 10 secondi.

Il metodo che utilizziamo è creare i due thread uno dopo l'altro usando la funzione pThread_create (). Quindi, chiamiamo prima la funzione pThread_join () con il thread in esecuzione più breve, seguita da una nuova chiamata a questa funzione con il thread in esecuzione più lungo. Quello che segue è il codice completo per questo esempio:

#includere
#includere
#includere
#includere
void* thread_f_1 (void* n);
void* thread_f_2 (void* n);
int main ()

pThread_t thread_1;
pThread_t thread_2;
pThread_create (& thread_1, null, thread_f_1, null);
pThread_create (& thread_2, null, thread_f_2, null);
pThread_Join (thread_1, null);
pThread_Join (thread_2, null);
restituzione 0;

void* thread_f_1 (void* n)

per (int a = 5; a!= 0; UN--)

printf ("Seconds to End of Thread 1: %i \ n", a);
sonno (1);

printf ("fine del thread 1 \ n");
pThread_exit (n);

void* thread_f_2 (void* n)

per (int a = 10; a!= 0; UN--)

printf ("Seconds to End of Thread 2: %i \ n", a);
sonno (1);

printf ("fine del thread 2 \ n");
pThread_exit (N);

Come vediamo nella seguente immagine, entrambi i thread hanno completato la loro esecuzione:

Errori che la funzione pThread_join () può restituire: cosa sono e come possono essere rilevati?

Quando si verifica un errore, la funzione pThread_join () restituisce uno dei seguenti codici predefiniti:

Esrch: L'identificatore specificato non è associato a nessun thread.

Einval: Il thread non è unito o un altro thread è già in attesa di unirsi a questo.

EDEADLK: Viene rilevato un incidente.

Questi errori sono predefiniti nel "errno.H ”” e vengono restituiti a causa del numero intero di output della funzione pThread_join (), non nella variabile globale errno.

Di seguito è riportato il codice dell'esempio precedente in cui aggiungiamo una condizione "if" per determinare se si è verificato un errore. In tal caso, il programma inserisce una condizione di switch che identifica l'errore e visualizza un messaggio nella console di comando con la descrizione specifica di tale errore.

Includiamo anche "errno.”H” e dichiarare la variabile di errore che saranno le condizioni “If” e “Switch”.

Per generare l'errore, ci riferiamo al thread_2 nell'argomento di input thread della funzione pThread_join () che non è creata.

#includere
#includere
#includere
#includere
#includere
void* thread_f (void* n);
int main ()
Errore int;
pThread_t thread_1;
pThread_t thread_2;
pThread_create (& thread_1, null, thread_f, null);
errore = pThread_Join (thread_2, null);
if (errore!= 0)
switch (errore)
Caso Esrch:
printf ("L'identificatore non è associato a nessun thread \ n");
rottura;
Caso Einval:
printf ("thread non unibile o un altro thread è già in attesa \ n");
rottura;
Caso Edeadlk:
printf ("è stato rilevato un incidente.\N");
rottura;

restituzione 0;

void* thread_f (void* n)

per (int a = 5; a!= 0; UN--)

printf ("Seconds to End of Thread: %i \ n", a);
sonno (1);

printf ("fine del thread \ n");
pThread_exit (N);

La seguente immagine mostra la compilazione e l'esecuzione di questo codice. Vedi come il programma inserisce l'istruzione "if" e l'istanza ESRCH dell'istruzione switch che indica che l'identificatore thread_2 punta a un thread inesistente. Puoi anche vedere che l'esecuzione di thread_1 è incompleta.

Conclusione

In questo articolo di Linux Sum.

Abbiamo spiegato la sintassi di questa funzione e descritto ciascuno dei suoi argomenti di input e come ottenere i dati che devono essere passati in essi. Abbiamo quindi implementato la funzione in un esempio pratico con frammenti di codice e immagini per mostrare come è possibile utilizzare la funzione pThread_join () per garantire un'esecuzione completa e affidabile di un thread.

Ti abbiamo anche mostrato come collegare correttamente la libreria thread per la compilation senza errori. In una sezione speciale, ti abbiamo mostrato come rilevare e identificare gli errori che la funzione PThread_Join () può generare.