Función PTHREAD_JOIN en lenguaje C con ejemplos de hilos únicos y múltiples

Función PTHREAD_JOIN en lenguaje C con ejemplos de hilos únicos y múltiples
El lenguaje C ofrece la posibilidad de desarrollar los programas de multitarea utilizando la biblioteca PTHREAD del estándar POSIX. Este método aumenta la velocidad del programa terminado ejecutando múltiples hilos en paralelo con la función principal.

Para crear un programa exitoso utilizando este método de programación, debe hacer algunas consideraciones especiales. Por ejemplo, si los tiempos de ejecución de un hilo son más largos que los de la función Main () y se ejecuta completamente, el programa terminará y también todos los hilos asociados, ya sea que hayan completado su tarea o no.

Esto puede causar problemas críticos porque un hilo que termina inesperadamente podría estar en el proceso de guardar los datos generados por el usuario, escribir en un archivo o dispositivo, o realizar alguna otra tarea importante.

En este artículo de Sugerencia de Linux, aprenderá cómo usar la función pthread_join () para asegurarse de que uno o más hilos se terminen de manera confiable antes de que salga un programa o se reanude.

Sintaxis de la función pthread_join () en lenguaje C

int pthread_join (pthread_t hilo, void ** retval);

Descripción de la función pthread_Join () en el lenguaje C

La función pthread_join () espera el proceso desde el que se llama hasta que un hilo ha terminado su tarea. Esta función suspende la función de la que se llama hasta que finaliza el subproceso que es especificado por su identificador en el argumento de entrada de subproceso.

Una vez que el hilo finaliza su tarea, el programa reanuda la ejecución de la siguiente línea del código que llama a pthread_join ().

Cuando finaliza el subprocesado, la función pthread_Join () devuelve el estado de salida del hilo en el argumento de Retval.

A continuación, vemos los argumentos de entrada al pthread_join () junto con una descripción de la función que satisface cada uno de esos argumentos:

hilo: Este argumento de entrada es un valor de datos del tipo pthread_t y es el identificador del subproceso que la función pthread_Join () debe esperar.

El valor del identificador es generado por el sistema y se obtiene como resultado de la función pthread_create () en su hilo de argumento de salida cuando se crea el hilo.

Retval: Este argumento de entrada es un puntero a (void *) donde la función pthread_join () almacena el estado de salida del hilo.

Si pthread_join () regresa correctamente, devuelve 0 como resultado. Si se produce un error, esta función devuelve un entero con un valor que representa el error que ocurrió. Más adelante, verá una sección especial que describe todos los errores que esta función puede generar y cómo identificarlos.

La función pthread_Join () se define en el PTHREAD.h encabezado. Para usarlo, los siguientes encabezados deben incluirse en el ".Archivo C ”, como se muestra en el siguiente:

#incluir
#incluir

Nota: Es importante que use esta función solo cuando sea necesario, ya que puede extender el tiempo de ejecución de un programa deteniendo un proceso para esperar a que el otro complete.

Errores de compilación en programas con hilos

Al compilar los programas GCC que usan subprocesos, la compilación puede fallar si no se realiza correctamente desde la línea de comando.

El mensaje de error más común emitido por el compilador establece que una de las funciones de hilo a las que nos referimos en el código no está definida.

Estos errores a menudo resultan en perder un tiempo valioso para verificar los encabezados que insertamos en el código, su integridad y los directorios asociados con el compilador, ya que todo indica que el problema está ahí está ahí.

Aunque las funciones que causan el error se definen en el "PTHREAD.H "encabezado y se incluyen en el código, el compilador no reconoce estas funciones a menos que la biblioteca PTHREAD se llame desde la línea de comando durante la compilación.

En la siguiente ilustración, puede ver la forma correcta de llamar a la biblioteca PTHread (resaltada en verde) desde la consola de comando durante la compilación de programas con hilos:

~ $ gcc -pthread ruta/nombre de archivo.c -o out_name

Como podemos ver en la siguiente figura, el error desaparece cuando se llama a la biblioteca PTHREAD durante la compilación.

Cómo usar la función pthread_join () para esperar a que un hilo complete la ejecución en el idioma C

En este ejemplo, creamos un hilo que tiene un tiempo de ejecución más largo que la función Main (). Después de crear el hilo, usamos el pthread_join () para esperar la ejecución completa del hilo antes de salir de la función main () y terminar el programa.

Para este propósito, creamos la función thread_f () que ejecuta el hilo. Esta función es un bucle "para" con 5 ciclos de una segunda duración, cada una de las cuales imprime el "Segundos al final del hilo:"Mensaje, seguido del número de segundos restantes en la consola de comando.

Desde la función main (), creamos el hilo_1 con la función pthread_create (). Luego, llamamos a la función pthread_join () para esperar a que el subproceso complete la ejecución antes de salir del programa.

La llamada de función pthread_Join () va con el identificador Thread_1 como el primer argumento de entrada y el Retval como NULL en el segundo argumento. Vemos el siguiente código completo para este ejemplo:

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

pthread_t thread_1;
pthread_create (& thread_1, null, thread_f, null);
pthread_join (Thread_1, nulo);
regresar 0;

void* thread_f (void* n)

para (int a = 5; a!= 0; a--)

printf ("segundos al final del hilo: %i \ n", a);
dormir (1);

printf ("End del hilo \ n");
pthread_exit (n);

La siguiente imagen muestra la compilación y ejecución de este código:

Como vimos en la figura, el bucle "para" completó sus 5 ciclos y el programa está cerrado después de que TREST_1 terminó su ejecución. Veamos qué sucede si eliminamos la función pthread_join (). Compilar y ejecutar el siguiente código:

Como podemos ver en la figura, el bucle "para" de Thread_1 no pudo completar un pase antes de que la función Main () esté completamente ejecutada y el programa termine.

Cómo usar la función pthread_join () para esperar a que un hilo múltiple complete la ejecución en el idioma C

En este ejemplo, le mostraremos cómo usar la función pthread_join () para esperar a que se completen múltiples hilos concurrentes.

Para hacer esto, usamos el código del ejemplo anterior y agregamos un segundo hilo que es Thread_2 y una segunda rutina que es Thread_F_2 () que se ejecuta en paralelo con Thread_1. El tiempo de ejecución de esta rutina es el doble que el de Thread_f_1 () que toma 10 segundos.

El método que usamos es crear los dos hilos uno tras otro usando la función pthread_create (). Luego, primero llamamos a la función pthread_join () con el hilo de ejecución más corto, seguido de una nueva llamada a esta función con el hilo de ejecución más largo. El siguiente es el código completo para este ejemplo:

#incluir
#incluir
#incluir
#incluir
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, nulo);
pthread_Join (Thread_2, NULL);
regresar 0;

void* thread_f_1 (void* n)

para (int a = 5; a!= 0; a--)

printf ("segundos al final del hilo 1: %i \ n", a);
dormir (1);

printf ("Fin del hilo 1 \ n");
pthread_exit (n);

void* thread_f_2 (void* n)

para (int a = 10; a!= 0; a--)

printf ("segundos al final del hilo 2: %i \ n", a);
dormir (1);

printf ("Fin del hilo 2 \ n");
pthread_exit (n);

Como vemos en la siguiente imagen, ambos hilos completaron su ejecución:

Errores que la función pthread_join () puede devolver: ¿cuáles son ellos y cómo se pueden detectar??

Cuando ocurre un error, la función pthread_join () devuelve uno de los siguientes códigos predefinidos:

Esrch: El identificador especificado no está asociado con ningún hilo.

Einval: El hilo no se puede unir o otro hilo ya está esperando unirse a este.

EDEADLK: Se detecta un choque.

Estos errores están predefinidos en el "Errno.encabezado h "y se devuelven como resultado en el entero de salida de la función pthread_join (), no en la variable global errno.

El siguiente es el código del ejemplo anterior en el que agregamos una condición "si" para determinar si ocurrió un error. Si es así, el programa ingresa una condición de interruptor que identifica el error y muestra un mensaje en la consola de comando con la descripción específica de ese error.

También incluimos el "Errno.H "encabezado y declare la variable de error que serán las condiciones de" si "y" cambiar ".

Para generar el error, nos referimos al hilo_2 en el argumento de entrada de hilo de la función pthread_join () que no se crea.

#incluir
#incluir
#incluir
#incluir
#incluir
void* thread_f (void* n);
int main ()
en terror;
pthread_t thread_1;
pthread_t thread_2;
pthread_create (& thread_1, null, thread_f, null);
error = pthread_Join (thread_2, null);
if (error!= 0)
Switch (Error)
Caso esrch:
printf ("El identificador no está asociado con ningún hilo \ n");
romper;
Caso Einval:
printf ("Hilo que no se puede unir u otro hilo ya está esperando \ n");
romper;
Caso edeadlk:
printf ("Se detectó un choque.\norte");
romper;

regresar 0;

void* thread_f (void* n)

para (int a = 5; a!= 0; a--)

printf ("segundos al final del hilo: %i \ n", a);
dormir (1);

printf ("End del hilo \ n");
pthread_exit (n);

La siguiente imagen muestra la compilación y ejecución de este código. Consulte cómo el programa ingresa a la instrucción "IF" y la instancia de ESRCH de la instrucción Switch que indica que el identificador Thread_2 apunta a un hilo inexistente. También puede ver que la ejecución de Thread_1 está incompleta.

Conclusión

En este artículo de Sugerencia de Linux, le mostramos cómo implementar la función pthread_join () desde la biblioteca de subprocesos para garantizar una ejecución completa de un subproceso.

Explicamos la sintaxis de esta función y describimos cada uno de sus argumentos de entrada y cómo obtener los datos que deben aprobarse en ellos. Luego implementamos la función en un ejemplo práctico con fragmentos e imágenes de código para mostrar cómo puede usar la función pthread_join () para garantizar una ejecución completa y confiable de un hilo.

También le mostramos cómo vincular correctamente la biblioteca de subprocesos para la compilación sin errores. En una sección especial, le mostramos cómo detectar e identificar los errores que puede generar la función pthread_join ().