Unidad 3. Programación Concurrente
PROGRAMACIÓN CONCURRENTE (MULTIHILOS)
Hace referencia a las
técnicas de programación que son utilizadas para expresar la concurrencia entre
tareas y solución de los problemas de comunicación y sincronización entre
procesos. La programación concurrente es la ejecución simultánea de múltiples
tareas interactivamente. Estas tareas pueden ser un conjunto de procesos o
hilos de ejecución creados por un único programa. Las tareas se pueden ejecutar
en una sola CPU (multiprogramación), en varios procesadores, o en una red de
computadores distribuidos.
En programación, nos
estamos refiriendo a los lenguajes de programación que permiten la ejecución de
varias tareas en forma simultánea.
Por ejemplo, consideremos la cantidad de aplicaciones que corren a la vez dentro de un mismo entrono gráfico. Mientras una persona escribe un documento, está corriendo Microsoft Windows además de Internet Explorer, Windows Explorer, CD Player y el Control de Volumen. Estas aplicaciones son ejecutadas dentro de alguna versión de Windows.
3.1
CONCEPTO DE HILO
Los hilos o threads, son básicamente, pequeños procesos o
piezas independientes de un gran proceso. También podemos decir, que un hilo es
un flujo único de ejecución dentro de un proceso (un proceso es un programa
ejecutándose dentro de su propio espacio de direcciones).
Un hilo no puede correr por sí mismo, se ejecuta dentro
de un programa, ya que requieren la supervisión de un proceso padre para
correr. Se pueden programar múltiples hilos de ejecución para que corran
simultáneamente en el mismo programa. La utilidad de la programación multihilo
resulta evidente. Por ejemplo, un navegador Web puede descargar un archivo de
un sitio, y acceder a otro sitio al mismo tiempo. Si el navegador puede
realizar simultáneamente dos tareas, no tendrá que esperar hasta que el archivo
haya terminado de descargarse para poder navegar a otro sitio.
Cuando se crea un
proceso el S.O crea su primer hilo (hilo primario) en la cual puede, a su vez,
crear hilos adicionales. esto pone de manifiesto que un proceso no ejecuta,
sino que es sólo el espacio de direcciones donde reside el código que es
ejecutado mediante uno o más hilos.
En un S.O tradicional. Cada proceso tiene un espacio de direcciones y un único hilo de control, por ejemplo, considere que un programa que incluya la siguiente secuencia de operaciones para actualizar el saldo de una cuenta bancaria cuando se efectúa un nuevo ingreso:
- Saldo=Cuenta.ObtenerSaldo ();
- Saldo+=ingreso;
- Cuenta.EstablecerSaldo (saldo);
Método |
Descripción |
final void
setName(String) |
Pone el nombre al hilo
actual |
final String
getName( ) |
Obtiene el nombre del
hilo actual |
Static sleep(long
milisegundos) throws InterruptedException |
Suspende un tiempo
para que se ejecute otro hilo. |
fnal void join( ) |
Espera a que los hilos
terminen |
final boolean
isAlive( ) |
Es para ver si está en
ejecución un hilo o si está activo. |
void run( ) |
Punto de entada de un
Hilo |
void start( ) |
Comienza un hilo
llamando a su método run |
final int
getPriority( ) |
Obtiene la prioridad
de un hilo |
final void
setPriority(int nivel) |
Establecer la
prioridad de un hilo. |
3.2
COMPARACIÓN DE UN PROGRAMA DE FLUJO ÚNICO CONTRA UNO DE FLUJO MÚLTIPLE.
PROGRAMAS DE FLUJO ÚNICO
Un programa de flujo único, tarea única o
mono -hilo (single-thread) utiliza un único flujo de control (thread) para
controlar su ejecución. Muchos programas no necesitan la potencia o utilidad de
múltiples tareas. Sin necesidad para especificar explícitamente que se quiere
un único flujo de control, muchos de los applets y aplicaciones son de flujo
único.
Un thread o hilo es, al igual que un proceso,
un flujo de control que puede gozar de cierta autonomía (puede tener sus
propias estructuras de datos), pero a diferencia de un proceso, diversos hilos
dentro de una aplicación pueden compartir los mismos datos.
PROGRAMAS DE FLUJO MÚLTIPLE
En la aplicación de Saludo, no se ve la tarea
que está ejecutando el programa. Sin embargo, java posibilita la creación de
tareas explícitamente. La utilización de las tareas (threads) en java permite
una enorme flexibilidad a los programadores a la hora de plantearse el
desarrollo de aplicaciones. La simplicidad para crear, configurar y ejecutar
tareas permite que se puedan implementar muy poderosas y portables
aplicaciones/applets que no se pueden crear con lenguajes de tercera
generación. En un lenguaje orientado a Internet como es Java, esta herramienta
es vital.
Si el lector a utilizado un navegador con
soporte en Java, ya habrá visto el uso de múltiples tareas en Java. Habrá
observado que dos applets se pueden ejecutar al mismo tiempo, o bien que puede
desplazar la página del navegador mientras el applet continúa ejecutándose.
Esto no significa que el applet utilice múltiples tareas, sino que el navegador
es multitareas, multihilo, multihilvanado o multithreaded.
3.3
CREACIÓN Y CONTROL DE HILOS
Un hilo
(en inglés “thread”) es la menor de las estructuras lógicas de programación que
se ejecuta de forma secuencial por parte del planificador del sistema operativo.
Encapsula todo el control necesario sobre los hilos de ejecución.
La
clase Thread es la única forma de controlar el comportamiento de los hilos.
Métodos de clase
Se mencionarán los métodos estáticos que deben llamarse de manera directa en la clase Thread:
- currentThread (): Este método devuelve el objeto thread que representa al hilo de ejecución que se está ejecutando actualmente.
- yield ():Este método hace que el intérprete cambie de contexto entre el hilo actual y el siguiente hilo ejecutable disponible. Es una manera de asegurar que nos hilos de menor prioridad no sufran inanición.
- sleep (long): El método sleep () provoca que el intérprete ponga al hilo en curso a dormir durante el número de milisegundos que se indiquen en el parámetro de invocación. Una vez transcurridos esos milisegundos, dicho hilo volverá a estar disponible para su ejecución.
Métodos de instancia
- start (): Este método indica al intérprete de Java que cree un contexto del hilo del sistema y comience a ejecutarlo. A continuación, el método run () de este hilo será invocado en el nuevo contexto del hilo.
- run ():El método run() constituye el cuerpo de un hilo en ejecución. Este es el único método del interfaz Runnable. Es llamado por el método start () después de que el hilo apropiado del sistema se haya inicializado. Siempre que el método run () devuelva el control, el hilo actual se detendrá.
- stop ():Este método provoca que el hilo se detenga de manera inmediata. A menudo constituye una manera brusca de detener un hilo, especialmente si este método se ejecuta sobre el hilo en curso.
Hay
dos modos de conseguir hilos de ejecución en Java:
1. Implementando el interfaz Runnable
Es la
forma habitual de crear hilos. Los interfaces proporcionan al programador una
forma de agrupar el trabajo de infraestructura de una clase.
2. 2.Extender
la clase Thread.
Pueden
implementar métodos y contener variables que no sean constantes. Segundo, un
interfaz no puede implementar cualquier método. Una clase que implemente un
interfaz debe implementar todos los métodos definidos en ese interfaz.
Un interfaz tiene la posibilidad de poder extenderse de otros interfaces y, al contrario que las clases, puede extenderse de múltiples interfaces.
3.4 SINCRONIZACIÓN DE HILOS COMPUTACIÓN
La razón más común para la
sincronización es cuando dos o más hilos necesitan acceso a un recurso
compartido que sólo puede ser utilizado por un hilo a la vez. Otra razón para
la sincronización es cuando un hilo está esperando un evento causado por otro
hilo. En este caso, debe de haber algún medio por el cual el primer hilo se
mantenga en estado suspendido hasta que el evento ocurra.
Uso de métodos Synchronized
Cuando se llama al método “Synchronized”, el
hilo que llama ingresa al monitor de objeto, que entonces bloquea el objeto.
Cuando un objeto está bloqueado por un hilo, ningún otro hilo puede obtener
acceso al objeto. Cuando el hilo sale, el objeto está desbloqueado y está
disponible para ser utilizado por otro hilo.
Se puede sincronizar el
acceso a un método modificándolo con la palabra clave. Cuando se llama a ese
método, el hilo de llamada entra en el monitor del objeto, que luego bloquea el
objeto.
- · Cuando está bloqueado, ningún otro hilo puede
ingresar al método, o ingresar cualquier otro método sincronizado definido por
la clase del objeto.
- · Cuando el hilo retorna del método, el monitor desbloquea el objeto, permitiendo que sea utilizado por el siguiente hilo. Por lo que se logra una sincronización
La
creación del método Synchronized dentro de las clases creadas por nosotros
mismos es fácil y eficiente sin embargo no trabaja en todos los casos.
La
forma general de un bloque Synchronized es:
- synchronized (objeto){
- //declaraciones para ser sincronizadas }
Aquí el objeto hace
referencia al objeto que va a ser sincronizado. Un objeto sincronizado asegura
que una llamada a un método ocurra solo después de que el hilo que llama ha
ingresado al monitor del objeto.
Comentarios
Publicar un comentario