En un S.O. multihilo nuestros programas pueden tener varios "hilos de ejecución", es decir, estar realizando (aparentemente) varias tareas a la vez. El programador escribe partes de su programa que se ejecutan en paralelo, y a estas partes las denominamos hilos. Pero a diferencia de escribir varios programas (procesos) que se ejecuten a la vez colaborativamente, los hilos comparten la memoria (es decir, acceden a las mismas variables globales o dinámicas), por lo que no necesitan de costosos mecanismos de comunicación entre procesos para sincronizarse.
Tampoco necesitan guardar gran parte de su contexto para preservar las variables, por lo que la penalización por cambio de contexto es menor.
Dentro de las técnicas para proporcional hilos al programador hay dos técnicas: los hilos en el espacio del kernel y los hilos en el espacio de usuario.
Los hilos del kernel son llamados a veces "procesos ligeros", porque pueden verse como una versión simplificada de los procesos. Es el kernel el que se encarga de darles soporte y de planificarlos. De hecho, la implementación actual de Linux de los hilos, LinuxThreads
incluye a los hilos en la cola de planificación de procesos, como si fueran un proceso más.
En os hilos a nivel de usuario, en cambio, es una biblioteca la encargada de realizar la multiprogramación por hilos. Esta biblioteca se enlaza con el programa principal, y ella es la que se encarga de proporcionar el soporte a una concurrencia (por supuesto, simulada) mediante un planificador interno. Esta técnica tiene algunas ventajas, especialmente máquinas multiprocesador -la planificación de hilos en procesadores diferentes acarrea penalizaciones por el hecho de no poder utilizar los datos de la memoria memoria caché de cada procesador- y también algunas desventajas. En linux podemos utilizar GNU pthreads como biblioteca de hilos a nivel de usuario.
En Unix los hilos suelen seguir la especificación POSIX, llamados comunmente POSIX Threads. La opinión de los algunos kernel hackers respecto a ellos ha sido muy explícita en el pasado:
"posix threads is a braindamaged pile of crap".
(Alan Cox)
"although a lot of the POSIX threads are reasonable, things like requiring uid/gid updates to be instantly effective across all threads in the process are just insane". (Stephen Tweedie)
"Note that the reason the kernel is not POSIX-compliant is:
- the POSIX standard is technically stupid. It's much better to use a cleaner fundamental threading model and build on top of that.
- things like the above are just so much better and more easily done in user space anyway."
(Linus Torvalds)
(obtenido de la edición de 30 marzo del 2000 de LWN).
Sin embargo, debido a su amplia utilización, se deseaba tener unos threads compatibles con POSIX disponibles a nivel de kernel a través de la glibc, y este es el hueco que viene a cubrir NPTL. La utilización de hilos permitirá por ejemplo mejorar el rendimiento de Apache (que aprovecha las características multihilo a partir de la versión 2.0) o de las aplicaciones Java, que suelen utilizar masivamente los hilos.
De hecho, gracias al nuevo parche O(1) de Ingo Molnar, el rendimiento en la creación y destrucción de hilos ha crecido espectacularmente. Según pruebas, se han llegado lanzar 100.000 hilos en 2 segundos, en vez de los 15 segundos que costaba antes (que es lo que se destaca en Slashdot de esta noticia). La ventaja del parche O(1) es que no hace falta recorrer una y otra vez la lista de procesos para decidir cual proceso (o hilo) debe entrar a ejecutarse, y cualquier mejora en un punto tan crítico como es el planificador tiene un impacto significativo. Quiero decir que una cosa son los parches de aumento de rendimiento del kernel, y otro el asunto de los nuevos hilos POSIX, y en la nota de Slashdot se han mezclado en cierta forma ambas cosas.
Espero no haber sido demasiado denso con las explicaciones, pero si queréis información más profunda y detallada, aquí dejo algunos enlaces más: