Un hilo es un proceso de peso ligero.
Un proceso es una secuencia de código que se ejecuta, así como todas las estructuras de datos de apoyo (mapa de memoria, recursos abiertos, pila, etc).
Si desea tener un código que se ejecuta en paralelo (ya sea porque hace que la programación sea más fácil, o porque quiere aprovechar las arquitecturas multi-CPU), puede ejecutar múltiples procesos, o múltiples hilos dentro de un proceso.
Un proceso puede contener uno o más hilos, y todos los hilos del mismo proceso comparten el mapa de memoria, los recursos abiertos, pero tienen sus propias pilas.
Hay pros y contras en cada enfoque. Por ejemplo, el uso de procesos le permite ejecutar programas independientes al mismo tiempo que pueden no haber sido escritos específicamente para trabajar entre sí. El uso de procesos también le da una mejor protección contra la interferencia involuntaria entre las tareas (que pueden ser maliciosas o simplemente errores de programación) – es por eso que Chrome utiliza un proceso por pestaña, por ejemplo, en lugar de hilos. También es por eso que Chrome suele ocupar mucha más memoria que Firefox, si abres un gran número de pestañas.
Por otro lado, usar hilos ahorra memoria, ya que se pueden compartir muchas cosas entre hilos. También facilitan la programación porque diferentes hilos en el mismo proceso pueden comunicarse simplemente usando variables compartidas (con la sincronización adecuada).
Incluso hay programas que te permiten elegir entre proceso vs hilos – un ejemplo que me viene a la mente es el servidor web de código abierto Apache.
Por defecto, Apache genera un nuevo proceso por cada conexión de cliente, y cada proceso sólo da servicio a un cliente. Sin embargo, puedes configurarlo para que utilice hilos en su lugar. El uso de hilos hace que se ejecute más rápido y utilice menos memoria en escenarios de alta carga, pero potencialmente a expensas de la seguridad (si hay un error en Apache y un atacante lo encuentra, puede ser capaz de acceder a otros hilos’ datos).