Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

37
Ingeniería en Sistemas Computacionales Tópicos Avanzados de Programación Unidad IV: Programación Concurrente (Multi-hilos) Este material está desarrollado para la asignatura Tópicos Avanzados de Programación, de la carrera de Ingeniería en Sistemas Computacionales, plan de estudios ISIC-2010-224 TÓPICOS AVANZADOS DE PROGRAMACIÓN

Transcript of Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Page 1: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Ingeniería en Sistemas Computacionales

Tópicos Avanzados de ProgramaciónUnidad IV: Programación Concurrente

(Multi-hilos)

Este material está desarrollado para la asignatura Tópicos Avanzados de Programación, de la carrera de Ingeniería en Sistemas Computacionales, plan de estudios ISIC-2010-224

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 2: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Competencia: Resolver problemas utilizando programación concurrente.

Page 3: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Concepto de hilo.

• Un hilo es un proceso que se está ejecutando en un momento determinado en nuestro sistema operativo, como cualquier otra tarea, esto se realiza directamente en el procesador. • Existen los llamados “demonios” que son los procesos que define el

sistema operativo en sí para poder funcionar y otros que llamaremos los hilos definidos por el usuario o por el programador, estos últimos son procesos a los que el programador define un comportamiento e inicia en un momento específico.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 4: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• En .NET, cuando se lanza una aplicación se crea un proceso y dentro de este proceso un hilo de ejecución o thread para el método main().

• Es posible, a la vez que se ejecuta el método main(), que la aplicación lance internamente nuevos hilos de ejecución en los que se ejecute el código de algún método.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 5: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• Un ejemplo muy actual de utilización de threads es una aplicación de tipo servidor Web, como el IIS, Apache Web Server, etc. • Un servidor Web es una aplicación que, al ser lanzada y creado para ella un

proceso y un hilo para el método main(), espera a que llegue una petición http de un cliente al puerto que escucha (el 80 generalmente) y cuando llega hace dos cosas:• Crea un nuevo hilo de ejecución o thread en el que atiende la petición.• Vuelve inmediatamente (en el hilo principal) a escuchar el puerto para

atender nuevas peticiones (mientras se atiende la petición en el nuevo hilo).

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 6: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• En equipos con menos procesadores que hilos o threads lanzados en un momento dado, se habla de concurrencia aparente, ya que todos los hilos no pueden estar ejecutándose a la vez.

• No obstante, no se ha de pensar que tener un solo procesador hace inútil lanzar más de un hilo o thread simultáneamente. Ni mucho menos, el 100% del tiempo de ejecución de un hilo no está ocupado el procesador (interacción con el usuario, entrada/salida, acceso a memoria), de modo que otro hilo puede aprovechar sus tiempos muertos.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 7: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• También es cierto que un exceso de threads o hilos resulta negativo, ya que se puede perder más tiempo “saltando” de un thread a otro que en la ejecución real (a esta operación se la llama “conmutación de contexto” e implica salvar y recuperar datos y registros de memoria).

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 8: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• En Windows, aunque sólo se disponga de un procesador, se permite ejecutar varios hilos simultáneamente (concurrencia aparente). Lo que se hace es ofrecer un tiempo determinado de ejecución (time slice o “rodaja de tiempo”) a cada hilo (realmente son milisegundos). Cuando ese tiempo finaliza, Windows retoma el control y se lo cede a otro thread. • De este modo se ofrece al usuario la ilusión de tener varias aplicaciones en

ejecución simultáneamente y también se optimiza el uso de los recursos. A este modo de organizar la ejecución de varios threads se le llama preemptive multitasking (“multitarea preemptiva”).• En realidad, el sistema operativo y cualquier hilo que se lance ya son dos

hilos, con lo cual la ejecución en Windows es siempre multihilo.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 9: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

La clase Thread.• Esta clase pertenece al namespace System.Threading. Para crear un thread

sólo hay que crear una instancia de esta clase. Sus métodos más importantes son:• start: lanza el thread a ejecución.• suspend: detiene momentáneamente la ejecución del thread.• resume: activa el thread suspendido, es decir, lo vuelve a poner en

ejecución.•abort: aborta o para de modo inmediato la ejecución del thread.• join: detiene el thread donde se invoca hasta que el thread para el que se

le invoca termina.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 10: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Las propiedades más interesantes de la clase Thread son:

• Name: permite darle un nombre a un thread que lo distinga del resto.

• CurrentThread: contiene una referencia al thread que está actualmente en ejecución.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 11: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Ejecución de un thread• Un thread no es más que un bloque de código vacío por defecto que es

posible lanzar a ejecución de modo simultáneo a otros threads.

• Supóngase que se desea crear una aplicación desde la que se lance un thread que referencie una función que muestre 10 veces un mensaje (“Hola, soy el thread”) en la consola. La aplicación lanzará también la función desde el thread principal de la aplicación (main).

• El código necesario para crearlo es el siguiente:

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 12: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 13: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Detener y activación de un Thread• Una vez un thread ha sido lanzado puede ser suspendido (suspend),

reactivado (resume) o abortado (abort). • suspend y resume: suspend suspende la ejecución de un thread

momentáneamente.• Un thread suspendido puede ser reactivado llamando a resume. Si no se

utilizan bien pueden causar situaciones de bloqueo no recuperables.• abort: lanza una excepción ThreadAbortException en el thread. El

tratamiento por defecto para esta excepción es finalizar la ejecución del thread. No obstante si se captura la excepción, se puede programar el tratamiento que se desee.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 14: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Propiedades Name y CurrentThread• Con la propiedad Name puede darse nombre a ambos threads; y• La propiedad CurrentThread puede obtenerse el thread principal para

darle nombre.

Propiedad Join• El método Join pertenece a la clase Thread y lo que hace es detener

la ejecución del thread donde se invoca hasta que el thread para el que se invoca termina.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 15: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Por ejemplo:

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 16: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPI

COS

AVAN

ZAD

OS

DE

PRO

GRA

MAC

IÓN

Page 17: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPI

COS

AVAN

ZAD

OS

DE

PRO

GRA

MAC

IÓN

Page 18: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Consideraciones

Application.Run(): Esta instrucción ejecuta una forma como aplicación, es la apropiada para abrir un nuevo hilo.

Application.Exit(): Cierra la aplicación actual. Se debe tener cuidado alutilizarla ya que si hay hilos que fueron ejecutados poresta aplicación se cerrarán también. Lo mejor es usarlasolo en el formulario principal.

this.close(): Esta instrucción es la más apropiada para cerrar unaforma que fue abierta como hilo ya que solo cierra elformulario o hilo actual pero no cierra la aplicación.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 19: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Ejercicio: Abecedario con Hilos

Realice un programa utilizando hilos que haga lo siguiente:

• Debe lanzar 10 hilos que desplieguen el abecedario inglés en minúsculas (códigos ascii del 65 al 90)• Cada hilo debe tener un nombre que haga referencia al número de hilo

actual y se debe desplegar cuando se lanza por primera vez, y también junto a cada letra del abecedario.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 20: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPI

COS

AVAN

ZAD

OS

DE

PRO

GRA

MAC

IÓN

Page 21: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPI

COS

AVAN

ZAD

OS

DE

PRO

GRA

MAC

IÓN

Page 22: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Prioridades• Cuando se lanzan varios threads para que se ejecuten simultáneamente, se

les asignan las “rodajas de tiempo” en función del valor que tenga su propiedad Priority.• La propiedad Priority es una propiedad pública de la clase Thread (no es

static). Realmente es una enumeración del tipo ThreadPriority, cuyos posibles valores son:

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 23: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Sincronización:• La sincronización de threads consiste en asegurar que distintos threads

acceden de modo coordinado a recursos compartidos.• El caso más sencillo es la sincronización del uso del procesador, lo cual se

lleva a cabo por el sistema operativo mediante la “multitarea preemptiva” (“rodajas de tiempo”).• Pero existen otras situaciones en las que la sincronización es necesaria y no

la hace por defecto el sistema operativo.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 24: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

lock• La sentencia lock bloquea el acceso a un bloque de código,

asegurando que sólo el thread que lo ha bloqueado tiene acceso a tal bloque.

Supóngase la siguiente clase:

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 25: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 26: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 27: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Clase System.Threading.Monitor• La clase Monitor implementa el concepto de monitor de

sincronización. Del mismo modo que existe esta clase existen otras como Mutex, etc.• la sentencia lock equivale a utilizar un Monitor llamando a sus

métodos Enter (al comienzo del bloque) y Exit (al final del bloque).

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 28: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Los métodos más importantes de la clase monitor son:• Enter: bloquea el segmento de código al que precede.• TryEnter: es similar a Enter pero no bloquea o produce sólo un bloqueo

temporal.• Exit: libera el bloque.• Wait: Detiene al thread que lo llama (muy importante, no bloquea el código

a otros threads sino que detiene al thread llamador) dejándolo en espera de que otro thread le notifique que puede seguir mediante el método Pulse. También libera el bloqueo que haya hecho ese thread si es que lo hay.• Pulse: notifica a un thread en la cola de espera (Wait) que puede continuar.• PulseAll: realiza la notificación a todos los threads de la cola de espera.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 29: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

A continuación, como ejemplo, se sustituye en el ejercicio anterior lock por las correpondientes llamadas a Enter y Exit en la clase Monitor.

int Realizar_Transaccion(int cantidad) {//comentar este método para ver el problema de no usarloMonitor.Enter(this);{if (saldo >= cantidad) {

Thread.Sleep(5);saldo = saldo - cantidad;System.Console.Write(Thread.CurrentThread.Name.ToString());System.Console.WriteLine ("-- Saldo= " +saldo.ToString());Monitor.Exit(this);return saldo;

} else

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 30: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

{ // continuacion del Else//si el balance es menor que la cantidad que se desea retirar//se deniega la transacciónSystem.Console.Write(Thread.CurrentThread.Name.ToString());System.Console.Write ("-- Transacción denegada.");System.Console.WriteLine ("-- El saldo sería= " +(saldo - cantidad));Monitor.Exit(this);return 0;

}}}Nota: Se puede observar que las llamadas a Exit han de ser antes de return o no se ejecutarán.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 31: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• Clase Mutex (Mutual Exclusion); Su funcionalidad es asegurar que solamente un hilo pueda tener a acceso a un recurso, o porción de código, esta clase puede ser usada para evitar que múltiples instancias de una aplicación sean iniciadas.• Aparentemente la funcionalidad de la clase Mutex es muy parecida a

Lock, una de las grandes diferencias entre ellas es que Mutex es una clase y Lock es una Instrucción, la funcionalidad de Mutex es mayor ya que permite manejar bloqueo a nivel de Sistema Operativo, de tal forma que actúa a nivel de proceso.• Cuando un Hilo adquiere una exclusión mutua (mutex), el siguiente Hilo

que intenta adquirir dicha exclusión mutua se suspende hasta que el primer subproceso libera la exclusión mutua.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 32: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• Existen dos tipo de exclusiones mutuas: exclusiones mutuas locales y exclusiones mutuas del sistema con nombre. • Si crea un objeto Mutex con un constructor que acepta un nombre, se

asocia a un objeto del sistema operativo con dicho nombre. Las exclusiones mutuas del sistema con nombre son visibles en todo el sistema operativo y se pueden utilizar para sincronizar las actividades de los procesos.• Con respecto al desempeño de la utilización de Mutex Vs Lock, La

instrucción Lock es mucho mas rápida que la utilización de la clase Mutex.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 33: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• Para utilizar la clase Mutex , se requiere el método WaitOne el cual obtiene el bloqueo exclusivo de un contenido a bloquear. Dicho bloque es liberado con el método ReleaseMutex. De la misma forma que se bloqueo con Lock , la clase Mutex puede ser liberada únicamente con la terminación del hilo que la llamo.

private static Mutex mut = new Mutex();

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 34: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• Ejemploprivate static Mutex mut = new Mutex();

public void Sumar() { mut.WaitOne(); Console.WriteLine("{0} Ingresando de Codigo Protegido", Thread.CurrentThread.Name); resultado = operador1 + operador2; //Bloqueamos el Hilo actual durante un segundo Thread.Sleep(1000); Console.WriteLine("El resultado de la Suma es:" + resultado); Console.WriteLine("{0} Saliendo de Codigo

Protegido\n",Thread.CurrentThread.Name); mut.ReleaseMutex();

}

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 35: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

Problema de los filósofos comensales:• Hay cinco filósofos sentados alrededor de una mesa que pasan su vida

cenando y pensando. Cada uno dispone de un plato de arroz y un palillo a la izquierda de su plato, pero para comer son necesarios dos palillos y cada filósofo sólo puede sujetar el que está a su izquierda o el que hay a su derecha. Con un solo palillo en la mano no tienen más remedio que esperar hasta que atrapen otro y puedan seguir comiendo.• Si dos filósofos adyacentes intentan tomar el mismo palillo a la vez se

produce una condición de carrera: ambos compiten por lo mismo pero uno se queda sin comer.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 36: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

• Si todos los filósofos cogen el palillo de su derecha al mismo tiempo, todos se quedarán esperando eternamente porque alguien debe liberar el palillo que les falta, cosa que nadie hará porque todos se encuentran en la misma situación (esperando que alguno deje su palillo). Llegado esto, los filósofos se morirán de hambre. A este bloqueo mutuo se le denomina interbloqueo o deadlock.

TÓPICOS AVANZADOS DE PROGRAMACIÓN

Page 37: Topicos Avanzados de Programacion - Unidad 4 programacion concurrente

El objetivo consiste en encontrar un recurso que permita que los filósofos nunca se mueran de hambre. Porque:

• Dos filósofos contiguos no pueden comer a la vez (exclusión mutua).• Si un filósofo está comiendo, los contiguos no pueden hacerlo hasta

que él termine (sincronización). • El filósofo que termina de comer debe ceder los palillos para su

posterior utilización (interbloqueo).

TÓPICOS AVANZADOS DE PROGRAMACIÓN