En informática , POSIX Threads , comúnmente conocido como pthreads , es un modelo de ejecución que existe independientemente de un lenguaje de programación , así como un modelo de ejecución paralela . Permite que un programa controle múltiples flujos de trabajo diferentes que se superponen en el tiempo. Cada flujo de trabajo se conoce como un hilo , y la creación y el control sobre estos flujos se logra haciendo llamadas a la API POSIX Threads . POSIX Threads es una API definida por el estándar POSIX .1c del Instituto de Ingenieros Eléctricos y Electrónicos (IEEE) , extensiones Threads (IEEE Std 1003.1c-1995) .
Las implementaciones de la API están disponibles en muchos sistemas operativos compatibles con POSIX similares a Unix, como FreeBSD , NetBSD , OpenBSD , Linux , macOS , Android [1] , Solaris , Redox y AUTOSAR Adaptive, generalmente incluidos como una biblioteca libpthread . También existen implementaciones de DR-DOS y Microsoft Windows : dentro del subsistema SFU/SUA , que proporciona una implementación nativa de varias API POSIX, y también dentro de paquetes de terceros como pthreads-w32 , [2] que implementa pthreads sobre la API de Windows existente .
pthreads define un conjunto de tipos , funciones y constantes del lenguaje de programación C. Se implementa con un encabezado y una biblioteca de subprocesos .pthread.h
Hay alrededor de 100 procedimientos de subprocesos, todos prefijados pthread_
y pueden clasificarse en cinco grupos:
La API de semáforo POSIX funciona con subprocesos POSIX pero no forma parte del estándar de subprocesos, ya que se definió en el estándar POSIX.1b, extensiones en tiempo real (IEEE Std 1003.1b-1993) . En consecuencia, los procedimientos de semáforo tienen como prefijo sem_
en lugar de pthread_
.
Un ejemplo que ilustra el uso de pthreads en C:
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <pthread.h> #include <unistd.h> #define NUM_HILOS 5void * perform_work ( void * arguments ){ int index = * (( int * ) arguments ); int sleep_time = 1 + rand () % NUM_THREADS ; printf ( "Hilo %d: Iniciado. \n " , índice ); printf ( "Hilo %d: Estará durmiendo durante %d segundos. \n " , índice , sleep_time ); sleep ( sleep_time ); printf ( "Hilo %d: Finalizado. \n " , índice ); return NULL ; } int main ( void ) { pthread_t hilos [ NUM_HILOS ]; int argumentos_hilo [ NUM_HILOS ]; int i ; int código_resultado ; //crear todos los hilos uno por uno for ( i = 0 ; i < NUM_HILOS ; i ++ ) { printf ( "En main: Creando hilo %d. \n " , i ); argumentos_hilo [ i ] = i ; código_resultado = pthread_create ( & hilos [ i ], NULL , realizar_trabajo , & argumentos_hilo [ i ]); assert ( ! código_resultado ); } printf ( "En principal: se crean todos los hilos. \n " ); //esperar a que cada hilo se complete for ( i = 0 ; i < NUM_THREADS ; i ++ ) { result_code = pthread_join ( threads [ i ], NULL ); assert ( ! result_code ); printf ( "En principal: el hilo %d ha finalizado. \n " , i ); } printf ( "El programa principal ha finalizado. \n " ); return 0 ; }
Este programa crea cinco subprocesos, cada uno de los cuales ejecuta la función perform_work que imprime el número único de este subproceso en la salida estándar. Si un programador quisiera que los subprocesos se comunicaran entre sí, esto requeriría definir una variable fuera del alcance de cualquiera de las funciones, convirtiéndola en una variable global . Este programa se puede compilar utilizando el compilador gcc con el siguiente comando:
gcc pthreads_demo.c -pthread -o pthreads_demo
Aquí se muestra uno de los muchos resultados posibles de la ejecución de este programa.
En principal: Creando hilo 0. En principal: Creando hilo 1. En principal: Creando hilo 2. En principal: Creando hilo 3. Hilo 0: Iniciado. En principal: Creando hilo 4. Hilo 3: Iniciado. Hilo 2: Iniciado. Hilo 0: Estará inactivo durante 3 segundos. Hilo 1: Iniciado. Hilo 1: Estará inactivo durante 5 segundos. Hilo 2: Estará inactivo durante 4 segundos. Hilo 4: Iniciado. Hilo 4: Estará inactivo durante 1 segundo. En principal: Se han creado todos los hilos. Hilo 3: Estará inactivo durante 4 segundos. Hilo 4: Finalizado. Hilo 0: Finalizado. En principal: El hilo 0 ha finalizado. Hilo 2: Finalizado. Hilo 3: Finalizado. Hilo 1: Finalizado. En principal: El hilo 1 ha finalizado. En principal: El hilo 2 ha finalizado. En principal: El hilo 3 ha finalizado. En principal: El hilo 4 ha finalizado. El programa principal ha finalizado.
Windows no soporta el estándar pthreads de forma nativa, por lo tanto el proyecto Pthreads4w busca proporcionar una implementación de contenedor portable y de código abierto . También puede usarse para portar software Unix (que usa pthreads) con poca o ninguna modificación a la plataforma Windows. [4] La versión 3.0.0 [5] o posterior de Pthreads4w, publicada bajo la Licencia Pública Apache v2.0, es compatible con sistemas Windows de 64 o 32 bits. La versión 2.11.0, [6] publicada bajo la licencia LGPLv3, también es compatible con sistemas de 64 o 32 bits.
El proyecto Mingw-w64 también contiene una implementación envolvente de 'pthreads, winpthreads' , que intenta utilizar más llamadas de sistema nativas que el proyecto Pthreads4w. [7]
El subsistema de entorno Interix disponible en el paquete Servicios de Windows para UNIX/Subsistema para aplicaciones basadas en UNIX proporciona un puerto nativo de la API pthreads, es decir, no está mapeado en la API Win32 sino construido directamente en la interfaz syscall del sistema operativo . [8]