Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Uso de hilos
¿Por qué alguien querría tener un tipo de proceso dentro de otro proceso?
Resulta ser que hay varias razones de tener estos miniprocesos, conocidos
como hilos. Ahora analizaremos algunos de ellos. La principal razón de tener
hilos es que en muchas aplicaciones se desarrollan varias actividades a la vez.
Algunas de ésas se pueden bloquear de vez en cuando. Al descomponer una
aplicación en varios hilos secuenciales que se ejecutan en cuasi-paralelo, el
modelo de programación se simplifica.
Un segundo argumento para tener hilos es que, como son más ligeros que los
procesos, son más fáciles de crear (es decir, rápidos) y destruir. En muchos
sistemas, la creación de un hilo es de 10 a 100 veces más rápida que la de un
proceso. Cuando el número de hilos necesarios cambia de manera dinámica y
rápida, es útil tener esta propiedad.
Por último, los hilos son útiles en los sistemas con varias CPUs, en donde es
posible el verdadero paralelismo. En el capítulo 8 volveremos a ver esta
cuestión.
Es más fácil ver por qué los hilos son útiles si utilizamos ejemplos concretos.
Como primer ejemplo considere un procesador de palabras. Por lo general, los
procesadores de palabras muestran el documento que se va crear en la
pantalla exactamente como aparecerá en la página impresa. En especial, todos
los saltos de línea y de página están en sus posiciones correctas y finales, de
manera que el usuario pueda inspeccionarlas y cambiar el documento si es
necesario (por ejemplo, para eliminar viudas y huérfanas, líneas superiores e
inferiores incompletas que se consideran estéticamente desagradables).
Suponga que el usuario está escribiendo un libro. Desde el punto de vista del
autor, es más fácil mantener todo el libro en un solo archivo para facilitar la
búsqueda de temas, realizar sustituciones globales, etc. También, cada
capítulo podría estar en un archivo separado; sin embargo, tener cada sección
y subsección como un archivo separado puede ser una verdadera molestia si
hay que realizar cambios globales en todo el libro, ya que entonces tendrían
que editarse cientos de archivos en forma individual. Por ejemplo, si se
aprueba el estándar xxxx propuesto justo antes de que el libro vaya a la
imprenta, todas las ocurrencias del “Estándar xxxx en borrador” tendrían que
cambiarse por “Estándar xxxx” a última hora. Si todo el libro está en un archivo,
por lo general un solo comando puede realizar todas las sustituciones. Por el
contrario, si el libro está esparcido en más de 300 archivos, cada uno se debe
editar por separado.
Si el programa tuviera sólo un hilo, entonces cada vez que iniciara un respaldo
en el disco se ignorarían los comandos del teclado y el ratón hasta que se
terminara el respaldo. El usuario sin duda consideraría esto como un
rendimiento pobre. De manera alternativa, los eventos de teclado y ratón
podrían interrumpir el respaldo en disco, permitiendo un buen rendimiento pero
produciendo un modelo de programación complejo, controlado por
interrupciones. Con tres hilos, el modelo de programación es mucho más
simple. El primer hilo interactúa sólo con el usuario, el segundo proceso vuelve
a dar formato al documento cuando se le indica y el tercero escribe el
contenido de la RAM al disco en forma periódica.
Hay una situación parecida con muchos otros programas interactivos. Por
ejemplo, una hoja de cálculo electrónica es un programa que permite a un
usuario mantener una matriz, de la cual algunos elementos son datos
proporcionados por el usuario. Otros elementos se calculan con base en los
datos de entrada, usando fórmulas potencialmente complejas. Cuando un
usuario modifica un elemento, tal vez haya que recalcular muchos otros
elementos. Al tener un hilo en segundo plano que realice esos cálculos, el hilo
interactivo puede permitir al usuario realizar modificaciones adiciona les
mientras el cálculo se está llevando a cabo. De manera similar, un tercer hilo se
puede encargar de los respaldos periódicos al disco por sí solo.
Ahora considere otro ejemplo más de la utilidad de los hilos: un servidor para
un sitio en World Wide Web. Las solicitudes de páginas llegan y la página
solicitada se envía de vuelta al cliente. En la mayoría de los sitios Web, algunas
páginas se visitan con más frecuencia que otras. Por ejemplo, la página de
inicio de Sony recibe muchas más visitas que una página a varios niveles de
profundidad en el árbol que contenga las especificaciones técnicas de cualquier
cámara de video. Los servidores Web utilizan este hecho para mejorar el
rendimiento, al mantener una colección de páginas de uso frecuente en la
memoria principal para eliminar la necesidad de ir al disco a obtenerlas. A dicha
colección se le conoce como caché y se utiliza en muchos otros contextos
también. Por ejemplo, en el capítulo 1 vimos las cachés de la CPU.
Considere la forma en que podría escribirse el servidor Web sin hilos. Una
posibilidad es hacer que opere como un solo hilo. El ciclo principal del servidor
Web recibe una petición, la examina y la lleva a cabo hasta completarla antes
de obtener la siguiente. Mientras espera al disco, el servidor está inactivo y no
procesa otras peticiones entrantes. Si el servidor Web se está ejecutando en
una máquina dedicada, como es común el caso, la CPU simplemente está
inactiva mientras el servidor Web espera al disco. El resultado neto es que se
pueden procesar menos peticiones/segundo. Por ende, los hilos obtienen un
aumento considerable en el rendimiento, pero cada hilo se programa de
manera secuencial, en forma usual.
Hasta ahora hemos visto dos posibles diseños: un servidor Web con multihilado
y un servidor Web con un solo hilo. Suponga que no hay hilos disponibles, pero
que los diseñadores del sistema consideran que la pérdida de rendimiento
debido a un solo hilo es inaceptable. Si hay una versión sin bloqueo de la
llamada al sistema read disponible, es posible un tercer diseño. Cuando entra
una petición, el único hilo existente la examina. Si se puede satisfacer desde la
caché está bien, pero si no es posible, se inicia una operación de disco sin
bloqueo.
Ahora el lector debe tener claro qué ofrecen los hilos: posibilitan el concepto de
procesos secuenciales que realizan llamadas al sistema con bloqueo (por
ejemplo, para la E/S de disco) y de todas formas logran un paralelismo. Las
llamadas al sistema con bloqueo facilitan el proceso de programación y el
paralelismo mejora el rendimiento. El servidor de un solo hilo retiene la
simpleza de las llamadas al sistema con bloqueo, pero pierde rendimiento. El
tercer método logra un alto rendimiento a través del paralelismo, pero utiliza
llamadas e interrupciones sin bloqueo y por ende, es difícil de programar. En la
figura 2-10 se sintetizan estos modelos.
Un tercer ejemplo en donde los hilos son de utilidad es en las aplicaciones que
deben procesar cantidades muy grandes de datos. El método normal es leer un
bloque de datos, procesarlo y después escribirlo nuevamente como salida. El
problema aquí es que, si sólo hay disponibles llamadas al sistema con bloqueo,
el proceso se bloquea mientas los datos están entrando y saliendo. Hacer que
la CPU quede inactiva cuando hay muchos cálculos que realizar es sin duda
muy ineficiente y debemos evitarlo siempre que sea posible.
Los hilos ofrecen una solución. El proceso podría estructurarse con un hilo de
entrada, un hilo de procesamiento y un hilo de salida. El hilo de entrada lee
datos y los coloca en un búfer de entrada. El hilo de procesamiento toma datos
del búfer de entrada, los procesa y coloca los resultados en un búfer de salida.
El búfer de salida escribe estos resultados de vuelta en el disco. De esta forma,
todas las operaciones de entrada, salida y procesamiento pueden estar
ocurriendo al mismo tiempo.
Desde luego que este modelo sólo funciona si una llamada al sistema bloquea
sólo al hilo que hizo la llamada, no a todo el proceso.