0% encontró este documento útil (0 votos)
59 vistas11 páginas

Introducción a los Hilos en Programación

El documento explica el concepto de hilos o threads en programación, destacando su papel como flujos de control dentro de un programa que comparten recursos y permiten la ejecución simultánea de tareas. Se detalla cómo los hilos mejoran la eficiencia y el rendimiento en sistemas multitarea, así como su implementación en código usando la biblioteca POSIX. Además, se discuten las ventajas de utilizar hilos, como la ejecución paralela, la velocidad de operaciones y la mejora en tiempos de respuesta.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
59 vistas11 páginas

Introducción a los Hilos en Programación

El documento explica el concepto de hilos o threads en programación, destacando su papel como flujos de control dentro de un programa que comparten recursos y permiten la ejecución simultánea de tareas. Se detalla cómo los hilos mejoran la eficiencia y el rendimiento en sistemas multitarea, así como su implementación en código usando la biblioteca POSIX. Además, se discuten las ventajas de utilizar hilos, como la ejecución paralela, la velocidad de operaciones y la mejora en tiempos de respuesta.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

Introducción de la actividad

Una thread es un único flujo de control dentro de un programa. Algunas veces es llamado
contexto de ejecución porque cada thread debe tener sus propios recursos, como el
program counter y el stack de ejecución, como el contexto de ejecución. Sin embargo,
toda thread en un programa aún comparte muchos recursos, tales como espacio de
memoria y archivos abiertos. Threads también son llamadas procesos livianos (lightweight
process).

NOTA: Es mucho más simple crear y destruir una thread que un proceso.

Los hilos, threads o subprocesos no forman parte física del procesador, no al menos en


lo que se refiere a más cantidad de núcleos o algo por el estilo.

Podemos definir un hilo de procesamiento como el flujo de control de datos de un


programa. Es un medio que permite administrar las tareas de un procesador y de sus
diferentes núcleos de una forma más eficiente. Gracias a los hilos, las unidades
mínimas de asignación, que son las tareas o procesos de un programa, pueden dividirse
en trozos para así optimizar los tiempos de espera de cada instrucción en la cola del
proceso. Estos trozos se llaman subprocesos o threads.

1
Dicho de otra forma, cada hilo de procesamiento contiene un trozo de la tarea a
realizar, algo más simple de realizar que si introducimos la tarea completa en el núcleo
físico. De esta forma la CPU es capaz de procesar varias tareas al mismo tiempo y de
forma simultánea, de hecho, podrá hacer tantas tareas como hilos tenga, y normalmente
son una o dos por cada núcleo. En los procesadores que tienen por ejemplo 6 núcleos y
12 hilos serán capaces de dividir los procesos en 12 tareas distintas en lugar de
solamente 6.

Esta forma de trabajar hace que los recursos del sistema sean administrados de forma
más equitativa y eficiente. Ya sabes…el divide y vencerás de toda la vida. Estos
procesadores se denominan multi-hilo. Por ahora, lo que debemos tener claro es que un
procesador con 12 hilos, no va a tener 12 núcleos, los núcleos son algo de origen físico y
los hilos algo de origen lógico.
Eso seguramente haya quedado algo abstracto y difícil de entender, así que vamos a ver
cómo se traduce si hablamos de la arquitectura de un programa en nuestro ordenador.

Breve descripción teórica sobre los hilos y su uso en sistemas


distribuidos

Todos sabemos qué es un programa, es un código que se almacena en nuestro


ordenador y que está destinado a llevar a cabo alguna tarea concreta. Una aplicación
es un programa, un driver también lo es e incluso el sistema operativo es un programa
capaz de ejecutar otros programas en su interior. Todos ellos están almacenados en
forma binaria, ya que el procesador solo entiende de unos y ceros, corriente / no
corriente.

2
Los procesos del programa

Para ejecutar un programa, este se carga en memoria, la memoria RAM. Este programa
es cargado mediante procesos, los cuales llevan su código binario asociado y los
recursos que necesita para operar, que serán asignados de forma “inteligente” por el
sistema operativo.
Los recursos básicos que necesita un proceso son, un contador de programa, y una pila
de registros.

 Contador de programa (CP): se llama puntero de instrucciones, y realiza el


seguimiento de la secuencia de instrucciones que se vayan procesando.
 Registros: es un almacén ubicado en el procesador en donde se puede guardar
una instrucción, una dirección de almacenamiento o cualquier otro dato.
 Pila: es la estructura de datos que almacena la información relativa a las
instancias que un programa tiene activas en el ordenador.
Entonces cada programa está dividido en procesos, y está almacenado en un lugar
determinado en memoria. Además, cada proceso se ejecuta de forma independiente, y
esto es muy importante de entender porque así es como el procesador y el sistema son
capaces de ejecutar varias tareas al mismo tiempo, lo que denominamos
sistema multitarea. Este sistema de procesamiento es el culpable de que podamos seguir
trabajando en nuestro PC, aunque un programa se haya quedado bloqueado.

Los hilos de un proceso

3
Aquí es donde hacen acto de presencia los hilos de procesamiento, denominados
subprocesos en los sistemas operativos. Un hilo es la unidad de ejecución de un
proceso. Podemos dividir el proceso en subprocesos, y cada uno de ellos será un hilo de
ejecución.
Si un programa no es multi-hilo, los procesos dentro de él solamente tendrán un hilo, así
que solamente se podrán procesar de una sola vez. Por el contrario, si tenemos
procesos multi-hilo, estos podrán dividirse en varios trozos, y cada uno de esos hilos
comparte los recursos asignados al proceso. Por eso dijimos que la ejecución en múltiples
hilos es más eficiente.

4
Además, cada hilo cuenta con su propia pila de registros por lo que podrán
procesarse dos o más de ellos al mismo tiempo, al contrario que un solo proceso, que
tendrá que ejecutarse todo de una sola vez. Los subprocesos son tareas más sencillas
que permiten ejecutar un proceso de forma dividida. Y esta es básicamente la función
final de los hilos de procesamiento. Cuantos más hilos, mayor división de procesos, y
mayor volumen de cálculos simultáneos y entonces, mayor eficiencia.
Código Fuente, con descripción de la aplicación, del código fuente y
uso de hilos

Los hilos reciben parámetros cuando son creados y devuelven un resultado una vez el
código ha finalizado. Este tipo de relación es similar a la que tiene un programa que ha
sido lanzado desde el terminal con su creador.

El siguiente trozo de código muestra un ejemplo de una aplicación con un hilo que recibe
por parámetro de entrada un número, lo incrementa en una unidad y devuelve dicho
resultado al hilo que lo ha invocado, que espera el resultado y lo imprime. (Nota:

5
los sleeps son didácticos y sirven para controlar el tiempo que tarda en ejecutarse una
hebra).

// compile with $ gcc -Wall -g *.c -pthread -o program


// run with ./program
// check with valgrind --tool=helgrind ./program
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

void* thread_run(void* data)


{ sleep(2);
printf("[TH_1:%ld]: Hello from the thread \n", pthread_self());
sleep(1);
(*(int*)data)++;
printf("[TH_1: %ld]: To exit...............\n",pthread_self());
pthread_exit(data);
}

int main()
{
pthread_t thread;
int data=0;
int thread_rc;
printf("[MAIN:%ld]: Starting............ \n",pthread_self());
if ((thread_rc=pthread_create(&thread,NULL,thread_run,&data))!=0)
{
printf("Error creating the thread. Code %i",thread_rc);
return -1;
}
sleep(1);
printf("[MAIN:%ld]: Thread allocated \n",pthread_self());
int *ptr_output_data;

6
pthread_join(thread,(void **)&ptr_output_data);
printf("[MAIN:%ld]: Thread returns %d \n",pthread_self(), *ptr_output_data);
return 0;
}

El código muestra el tipo de interacción que se puede realizar con los hilos POSIX.
Veamos algunos puntos de interés del código:

 Para poder utilizar la interfaz de los hilos es necesario incluir la


cabecera pthread.h. Además, a la hora de compilar hay que enlazar el código con
la opción -lpthread.
 La creación de un hilo se hace mediante pthread_create. A partir de este punto, si
la función no produce error, hay dos hilos de ejecución: el del programa invocante
y otro cuyo nombre de función se pasa por parámetro y en nuestro caso se
corresponde con thread_run. Dicha función recibe un puntero a datos y devuelve
otro. Típicamente, el hilo invocante usa el último parametro de hilo para enviar
datos de entrada al nuevo hilo.
 El resultado del hilo se devuelve cuando la función con la que se crea el hilo
finaliza. El hilo devuelve un puntero cuyos resultados se pueden recoger, más
tarde, con pthread_join desde el hilo padre que lo ha creado.

Cuando se compila el código y se ejecuta, se puede ver como cada hilo genera diferentes
mensajes de forma independiente. Eso es típico de la programación concurrente pues
cada hebra trabaja a una velocidad diferente.

Pantallas de ejecución con resultados en entorno amigable

La ejecución de cada hilo es independiente, o más bien, se ejecuta concurrentemente con


el resto y lo que genera la siguiente traza:

./pthreads_create_join_main
[MAIN -1219377472]: Starting............

7
[TH_1 -1219380416]: Hello from the thread
[MAIN -1219377472]: Thread allocated
[TH_1 -1219380416]: To exit...............
[MAIN -1219377472]: Thread returns 1

En esta ejecución se ha jugado con los tiempos del sleep de la aplicación para que los
mensajes del hilo principal y del hilo secundario se intercalen. Esto se consigue metiendo
un sleep que genera una secuencia predecible, donde en principio esto no es tan sencillo
de conseguir.

Alguna de las propiedades que se pueden controlar incluye la particularización de los


siguientes parámetros:

 La configuración de si hilo padre esperará o no por un resultado de su hilo cuando


haga pthread_join. Esto se controla mediante pthread_attr_setdetachstate.
 El tamaño de la pila donde se ejecuta el hilo. Esto es controlable
mediante pthread_attr_setstacksize.

Conclusiones de la actividad haciendo análisis e interpretación de los


resultados destacando la importancia del uso de hilos en sistemas
distribuidos, indicando sus principales beneficios

El concepto de multitarea o multiprocesamiento es bastante sencillo de entender ya


que solo consiste en hacer varias cosas a la vez sin que se vea alterado el resultado
final. Como ya se ha dicho en la entrada no todo se puede paralelizar y en muchas
ocasiones suele ser complicado encontrar la manera de paralelizar procesos dentro de
una aplicación sin que esta afecte al resultado de la misma, por tanto, aunque el
concepto sea fácil de entender el aplicarlo a un caso práctico puede ser complicado
para que el resultado de la aplicación no se vea afectado.

La principal ventaja de los hilos es el rendimiento. Normalmente el rendimiento es una


cantidad percibida y no dada. Unas aplicaciones se beneficiarán de los hilos mientras que
otras no. Como se suele decir "el número de kilómetros puede variar".

8
Existen un gran número de ventajas para emplear los hilos de usuario, así como los hilos
del núcleo:

1. Ejecución paralela: Los hilos de nivel kernel se pueden ejecutar realmente en


paralelo en máquinas SMP (Symmetric Multiprocessors). Además, el mismo
código binario es válido tanto para una máquina de un procesador como una
máquina multiprocesador.
2. Ejecución de código asíncrono: Ya que existen múltiples hilos de ejecución en
un programa construido con hilos, es posible que otro hilo del mismo proceso sea
planificado para ejecutar en el caso de que el hilo de ejecución actual se bloquee.
Esto incrementa la probabilidad de que la aplicación asociada se ejecute mucho
más rápido. Normalmente existen algunas cosas a tener en cuenta:
3.
1. En el modelo de hilos de usuario, algunos bloqueos bloquearán todo el
proceso y se planificará un proceso diferente.
2. En el modelo de hilos de núcleo, es posible que un hilo de otro proceso sea
planificado cuando sucede un bloqueo del hilo actual.
3. En ambos modelos, un hilo puede bloquearse y pueden no existir otros
hilos listos para ejecutarse en el proceso, por cualquier tipo de razones.

Así pues, el incremento del rendimiento no siempre está garantizado, aunque al menos, el
uso de los hilos puede incrementar la probabilidad de un mejor rendimiento.

1. Recursos compartidos: Los hilos comparten la mayoría de los recursos en un


proceso. Comparten el acceso a los ficheros, memoria compartida, y el espacio de
direcciones virtual. El empleo de los hilos permite a los programadores conservar
los recursos del sistema. El rendimiento puede beneficiarse también porque los
recursos compartidos entre hilos necesitan menos gestión que los recursos
compartidos entre procesos.
2. Velocidad de las operaciones con hilos: Los hilos tienen un menor contexto que
los procesos, así pues, las operaciones con hilos son generalmente más rápidas
que las operaciones similares con procesos. En especial, la creación, finalización y
cambio de contexto de un hilo, son operaciones más rápidas con los hilos que con
los procesos. Como ejemplo, en los procesadores de propósito general (SPARC,
MIPS, ALPHA, HP-PA, x86) el cambio de contexto entre hilos de un mismo

9
proceso lleva del orden de 50us. mientras que el cambio de contexto entre hilos de
distintos procesos lleva del orden de 100us. Estos tiempos son muy inferiores al
tiempo de cambio de contexto completo entre procesos. Así en Solaris la creación
de un proceso es unas 30 veces más lento que la creación de un hilo, las variables
de sincronización son unas 10 veces más lentas y el cambio de contexto unas 5
veces más lento.
3. Tiempo de respuesta: Si es posible separar operaciones en un programa, los
hilos se pueden emplear para mejorar los tiempos de respuesta de la aplicación.
Por ejemplo, supongamos que estamos usando una utilidad de correo electrónico.
En una versión de un solo hilo, mientras almacenamos un mensaje podemos
apreciar algún retraso antes de que la interfaz de usuario sea refrescada. Esto es
porque el programa está primero haciendo una operación de E/S para almacenar
el mensaje y después refresca la pantalla. Estas operaciones las realiza de forma
secuencial. Normalmente, si esta aplicación fuese una versión programada con
varios hilos, un hilo podría gestionar la E/S mientras otro hilo gestiona la interfaz
de usuario. Estas operaciones pueden funcionar en paralelo, con la consiguiente
ganancia en el tiempo de respuesta.
4. Programación natural: Esta ventaja no está relacionada con el rendimiento, pero
es importante. En algunas aplicaciones, el diseñador puede necesitar
instrucciones del tipo 'goto' y otros métodos para superar las limitaciones de la
programación secuencial tradicional. Sin embargo, con los hilos, el programador
no está limitado a emplear un modelo de ejecución secuencial. Así, las
limitaciones de la programación secuencial pueden solucionarse de forma más
intuitiva, menos compleja y más natural, incluso empleando otros modelos de
programación, como la programación concurrente. Además, muchos problemas
son más fáciles de plantear y programar con un modelo de hilos debido a su
estructura concurrente.
5. Existe un estándar (POSIX 1003.1c) lo que permite hacer a las aplicaciones
portables entre distintas plataformas. El mismo código fuente es válido para
distintas plataformas.
6. Objetos distribuidos: Con la aparición del estándar de objetos distribuidos
CORBA, los hilos toman un papel especial e importante. Los objetos distribuidos
tienen una estructura multihilo inherentemente. Cada vez que se pide que un
objeto realice una acción, el objeto ejecuta la acción mediante un hilo

10
independiente, de forma que el objeto puede haber más de un hilo al mismo
tiempo. Además, los servidores de objetos se pueden construir con hilos de forma
más efectiva y con un mayor rendimiento.

Bibliografía

 Sistemas Operativos
Jesús Manuel Silva Martínez
Alfa omega Grupo Editor
 Sistemas Distribuidos Principios y Paradigmas
André S. Tanembaum
Prentice Hall
Segunda Edición

11

También podría gustarte