La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Procesos e hilos Juan Camilo Jiménez Dorado

Presentaciones similares


Presentación del tema: "Procesos e hilos Juan Camilo Jiménez Dorado"— Transcripción de la presentación:

1 Procesos e hilos Juan Camilo Jiménez Dorado supercamilo@gmail.com
Diciembre 2011

2 Procesos Ejecución de un programa compuesto por: Instrucciones Estado
Memoria de trabajo Información de planificación

3 Estados de un proceso Unidad mínima de asignación de recursos: Proceso (Tarea).

4 Hilos Sub rutinas ejecutándose dentro de un proceso. Se usan cuando:
El hilo principal no es suficientemente veloz. Se necesita procesamiento asincrónico. Se necesita procesamiento en paralelo. Se va a realizar procesamiento en batch. Se van a recibir peticiones simultaneas. (como lo hacen ASP.NET, WCF, Web Services, or Remoting)

5 Estados de un Hilo Unidad mínima de expedición de recursos: Hilo. (comparten recursos)

6 Estados de un Hilo Estado Descripción Running
El subproceso se ha iniciado, no está bloqueado y no existe una excepción ThreadAbortException pendiente. StopRequested Se ha solicitado que el subproceso se detenga. Esto último sólo se refiere al uso interno. SuspendRequested El subproceso se ha marcado para suspensión. Background El subproceso está ejecutándose como subproceso en segundo plano, por oposición a un subproceso en primer plano. Para controlar este estado, hay que establecer la propiedad Thread.IsBackground. Unstarted No se ha invocado al método Thread.Start en el subproceso. Stopped El subproceso se ha detenido. WaitSleepJoin Subproceso bloqueado. Este podría ser el resultado de llamar a Thread.Sleep o Thread.Join, de solicitar un bloqueo (por ejemplo, llamando a Monitor.Enter o Monitor.Wait) o de esperar en un objeto de sincronización de subprocesos como ManualResetEvent. Suspended El subproceso se ha suspendido. AbortRequested Se ha invocado al método Thread.Abort en el subproceso, pero el subproceso aún no ha recibido la excepciónSystem.Threading.ThreadAbortException pendiente que intentará finalizarlo. Aborted El estado del subproceso incluye AbortRequested y el subproceso está ahora inactivo, pero su estado no ha cambiado todavía aStopped.

7 Estados de un Hilo Acción ThreadState
Se crea un subproceso dentro de Common Language Runtime. Unstarted Otro subproceso llama al método Start del subproceso. El subproceso comienza a ejecutarse. Running El subproceso llama a Sleep. WaitSleepJoin El subproceso llama a Wait o realiza alguna otra llamada de bloqueo. El subproceso llama a Join en otro subproceso. Common Language Runtime marca el subproceso de suspensión, por ejemplo, para realizar la recolección de elementos no utilizados. SuspendRequested Subproceso suspendido. Suspended El subproceso se reanuda después de que haya sido suspendido. Otro subproceso llama a Thread.Abort en el subproceso. AbortRequested Subproceso finalizado. Stopped El propio subproceso u otro ha establecido la propiedad Thread.IsBackground del subproceso en true. Background

8 Estados de un Hilo

9 Multithreading vs. Procesos
Se tarda mucho menos tiempo en crear un hilo nuevo en un proceso existente que en crear un proceso. Se tarda mucho menos en terminar un hilo que un proceso. Se tarda mucho menos tiempo en cambiar entre dos hilos de un mismo proceso. Los hilos aumentan la eficiencia de la comunicación entre programas en ejecución.

10 Desventajas de los hilos
Incrementan la complejidad de la aplicación. No siempre a mayor número de hilos mayor performance. El número incorrecto de hilos puede perjudicar el rendimiento. En operaciones de escritura de disco, muchos hilos perjudican el porformance.

11 Hilo principal Punto de entrada de un proceso.
Puede dar inicio a los demás hilos

12 Ámbito de un hilo class Program { static void Main() {
{   static void Main()   {     Thread t = new Thread (WriteY);          // Crear un nuevo hilo secundario    t.Start();                               // Iniciar hilo secundario  // Imprimir X en el hilo principal    for (int i = 0; i < 1000; i++) Console.Write ("x");   }   static void WriteY()   // Imprimir Y en el hilo secundario for (int i = 0; i < 1000; i++) Console.Write ("y");   }

13 Hilos compartiendo datos
public static void main() { new Thread(Go).Start(); // Llama GoShare() en un nuevo hiloo Go(); // Llama GoShare() en el hilo principal } static void Go() // Imprime ? 5 veces cada que lo llamen for (int cycles = 0; cycles < 5; cycles++) Console.Write('?'); bool done; public static void main() { ShareSameInstance tt = new ShareSameInstance(); // Crea una instancia común de la clase program new Thread(tt.Go).Start(); tt.Go(); } // Go() pasa a ser un método de instancia void Go() if (!done) { done = true; Console.WriteLine("Done"); } Nota: Tambien se pueden datos a través de variables estáticas

14 Join Espera hasta que un hilo termine para continuar con la ejecución.
static void main() { Thread t = new Thread(Go); t.Start(); t.Join(); Console.WriteLine("El hilo ha terminado!"); } static void Go() for (int i = 0; i < 1000; i++) Console.Write("y"); Se puede usar un TimeSpan para elegir un time out t.Join(TimeSpan.FromSeconds(2));

15 Sleep Suspende un hilo por un tiempo determinado
Thread.Sleep(TimeSpan.FromMinutes(1)); Nota: Mientras se usa Sleep o Join, el hilo está bloqueado y no consume recursos de CPU

16 Interrupt / Abort Interrupt desbloquea hilos previamente bloqueados, mientras que abort los interrupe así no estén bloqueados. Interrupt espera hasta el próximo bloqueo del hilo para ejecutar las demás instrucciones. UnSafe Safe public static void main() { Thread t = new Thread(Go); t.Start(); t.Abort(); } static void Go() while (true) // Imprime X hasta que se cancela Console.Write('X'); public static void main() { var cancelSource = new CancellationTokenSource(); new Thread(() => Go(cancelSource.Token)).Start(); cancelSource.Cancel(); } static void Go(CancellationToken cancelToken) cancelToken.ThrowIfCancellationRequested(); // Imprime X hasta que se cancela for (int cycles = 0; cycles < 5; cycles++) Console.Write('X'); Nota: la operación abort es insegura en la mayoría de escenarios, por ejemplo, cuando se está escribiendo en disco.

17 Ejercicio #1 (Estados de los hilos)
Usando el formulario frmThreadingStates en el proyecto Threading2, implemente cada una de las operaciones básicas de un hilo usando cada botón de la interfaz gráfica y mostrando los valores asignando texto a la variable global “text”.

18 Nombrar hilos Los hilos se pueden nombrar para identificarlos en tiempo de ejecución. public static void main() { Thread.CurrentThread.Name = "main"; Thread worker = new Thread(Go); worker.Name = "worker"; worker.Start(); Go(); } static void Go() Console.WriteLine("Este es el hilo " + Thread.CurrentThread.Name); De esta manera se pueden ver en el Threads Window.

19 Pasar parametros a un hilo
Usando expresiones Lambda: public static void main() { Thread t = new Thread(() => Print("Hola mundo!")); t.Start(); } static void Print(string message) Console.WriteLine(message); Usando ParameterizedThreadStart: public static void main() { Thread tt = new Thread(new ParameterizedThreadStart(PrintB)); tt.Start("Hola mundo B!"); } static void PrintB(object message) Console.WriteLine(message);

20 Foreground y Background
Los hilos tipo foreground mantienen la aplicación viva mientras al menos uno de ellos esté corriendo. public static void main() { //Los hilos son foreground por defecto Thread worker = new Thread(() => Console.ReadLine()); worker.Start(); //El hilo principal termina pero la aplicación porque el hilo worker es foreground por defecto } Una vez finalizan todos los hilos foreground, todos los hilos background son matados súbitamente. public static void main() { Thread worker = new Thread(() => Console.ReadLine()); worker.IsBackground = true; worker.Start(); //El hilo principal termina y mata al hilo secundario inmediatamente por ser background }

21 Prioridad Determina cual es su tiempo de ejecución relativo a otros hilos por parte del sistema operativo relativo. enum ThreadPriority { Lowest, BelowNormal, Normal, AboveNormal, Highest } worker.Priority = ThreadPriority.Highest; También es posible alterar la prioridad de los procesos, especialmente para trabajo en tiempo real using (Process p = Process.GetCurrentProcess()) p.PriorityClass = ProcessPriorityClass.High; Nota: La prioridad de un hilo se debe escoger cuidadosamente para no sobrecargar la CPU.

22 Manejo de excepciones Las excepciones no tienen sentido en el ámbito de la función que inicia el hilo: public static void main() { try new Thread(Go).Start(); } catch (System.Exception ex) // nunca llega aqui! Console.WriteLine("Exception!"); Las excepciones se deben controlar en la función del hilo: static void Go() { try throw null; } catch (System.Exception ex) // Captura la excepción Console.WriteLine("Exception en el Go!");

23 Arreglos de hilos private static Thread[] TArray;
public static void main() { ThreadArray ta; //declaramos un arreglo de 5 hilos TArray = new Thread[5]; for (int i = 0; i < TArray.Length; i++) ta = new ThreadArray(); TArray[i] = new Thread(new ParameterizedThreadStart(ta.Go)); } //iniciamos los 5 hilos pasando como parametro el número de cada hilo para que imprima TArray[i].Start(i+1); } //Iniciamos un hilo con prioridad alta imprimiendo x Thread t = new Thread(() => ta.Go("x")); t.Start(); void Go(object num) for (int i = 0; i < 100; i++) Console.Write(num.ToString());

24 Ejercicio #2 (Otros aspectos importantes de los hilos)
Implemente una rutina con un arreglo de hilos que imprima los números del 1 al 10, 100 veces cada uno y al mismo tiempo inicie otro hilo que imprima su nombre 200 veces con mayor prioridad que los números. Una vez impreso su nombre 200 veces, generar una excepción que en su catch aborte todos los hilos de los números.

25 Sincronización de hilos
Coordinación de las acciones de los hilos. Dividida en 4 tipos: Bloqueo simple: Sleep, Join, Task.Wait. Locking: Lock, Mutex, SpinLock Nonblocking: Semaphores Signaling:

26 Thread safety Cuando dos hilos intentan acceder al mismo recurso al mismo tiempo es thread unsafe. static bool done; // Los campos estáticos se comparten en todos los hilos public static void main() { new Thread(Go).Start(); Go(); } static void Go() //mientras un hilo está evaluando el if el otro puede estar haciendo el writeline antes de poner done=true if (!done) { Console.WriteLine("Done"); done = true; }

27 Bloqueo vs Spinning El spinning puede servir para poner a los hilos a esperar pero puede acarrear problemas de concurrencia. static DateTime flag; public static void main() { flag = DateTime.Now.AddSeconds(-40); Thread t = new Thread(Go); t.Start(); t.Join(); Console.Write("El hilo ha terminado!"); } static void Go() while (flag < DateTime.Now) Console.Write("y");

28 Locking Asegura que solo un hilo acceda a cierta porción de código
static bool done; static readonly object locker = new object(); public static void main() { new Thread(Go).Start(); Go(); } static void Go() lock (locker) if (!done) { Console.WriteLine("Done"); done = true; } Cuando un hilo se enfrenta a un lock, este se pone en estado blocked (waiting) y espera hasta que se desbloquee la porción de código. Nota: La regla de oro del locking es usarlo en cualquier operación de asignación de variables.

29 Ejercicio #3 (Locking) Considere la siguiente clase:
Identifique el error que se produciría si otro hilo llamara a la función Go(). Implemente otro hilo llamando a la función Go para reproducir el error. Resuelva el error usando los conocimientos adquiridos. class ThreadUnsafe {   static int _val1 = 1, _val2 = 1; public static void main() Thread t = new Thread(Go); t.Start(); }   static void Go()   {     if (_val2 != 0) Console.WriteLine (_val1 / _val2);     _val2 = 0;   }

30 Semaphore Es como una discoteca, tiene una capacidad limitada y una vez se llena no puede entrar nadie hasta que salga otra persona. El Lock() y el Mutex() son como semaphores con capacidad de 1. Los semaphores son muy útiles para limitar el número de hilos que acceden a cierta función y así controlar la concurrencia. static SemaphoreSlim _sem = new SemaphoreSlim(3); // capacidad 3 public static void main() { //5 hilos tratando de entrar for (int i = 1; i <= 5; i++) new Thread(Enter).Start(i); } static void Enter(object id) Console.WriteLine(id + " quiere entrar"); _sem.Wait(); // sólo 3 hilos pueden estar aqui al mismo tiempo Console.WriteLine(id + " está adentro!"); Thread.Sleep(1000 * (int)id); Console.WriteLine(id + " está saliendo"); _sem.Release(); Nota: contrario a Lock() y Mutex(), los semaphores no tienen dueño, es decir, cualquier hilo los puede liberar.

31 Signaling El signaling se apoya en los Event Wait Handles para lograr que un hilo espere confirmación de otro hilo para realizar acciones específicas. A continuación se muestran los diversos tipos de Event Wait Handles soportados por .NET: Constructor Proposito Cross-process? AutoResetEvent Permite a un hilo desbloquearse apenas reciba una señal de otro hilo. Si ManualResetEvent Permite a un hilo desbloquearse indefinidamente cuando recibe una señal de otro hilo (hasta que ocurra un reset). ManualResetEventSlim - CountdownEvent Permite a un hilo desbloquearse cuando recibe un número determinado de señales. Barrier Implementa una barrera de ejecución de hilo Wait and Pulse Permite a un hilo desbloquearse cuando se cumpla cierta condición.

32 AutoResetEvent Igual que cuando un usuario del metro mete su ticket en el torniquete, este se desbloquea automaticamente para dejar meter otro ticket cuando el usuario pasa. Solo un ticket por usuario. static EventWaitHandle _waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); public static void main() { new Thread(Waiter).Start(); //Pausa el hilo principal por 1 segundo Thread.Sleep(1000); // Envía la señal a los waiter para despertarlos _waitHandle.Set(); } static void Waiter() Console.WriteLine("Esperando..."); // espera por la notificación del hilo principal, que puede no llegarle porque esa señal la usa otro Waiter _waitHandle.WaitOne(); Console.WriteLine("Notificado!");

33 ManualResetEvent Funciona como una puerta ordinaria, cuando la puerta se abre todos los hilos pasan y cuando se cierra ya no pasan mas hilos. Al usar Set() se abre la puerta, permitiendo a todos los hilos en espera continuar. Al usar Reset() se cierra la puerta. static EventWaitHandle _waitHandle = new System.Threading.ManualResetEvent(false); public static void main() { new Thread(Waiter).Start(); new Thread(Waiter2).Start(); //Pausa el hilo principal por 1 segundo Thread.Sleep(1000); //Envía la señal a los dos waiter para despertarlos _waitHandle.Set(); } static void Waiter() Console.WriteLine("Esperando..."); //esperar por la notificación del hilo principal _waitHandle.WaitOne(); Console.WriteLine("Notificado 1!"); static void Waiter2() Console.WriteLine("Notificado 2!");

34 CountdownEvent Espera un número determinado de señales para desbloquear. static CountdownEvent _countdown = new CountdownEvent(3); public static void main() { new Thread(SaySomething).Start("Hilo 1"); new Thread(SaySomething).Start("Hilo 2"); new Thread(SaySomething).Start("Hilo 3"); //Bloquea hasta que la señal haya llegado 3 veces _countdown.Wait(); Console.WriteLine("Todos los hilos han terminado de comunicarse!"); } static void SaySomething(object thing) Thread.Sleep(1000); Console.WriteLine(thing); _countdown.Signal();

35 Signaling en doble vía Es posible que la comunicación entre dos hilos se haga en doble vía usando dos Event Wait Handle, de esta manera se pueden resolver escenarios dónde un hilo debe notificar mas de una vez al otro. static EventWaitHandle _ready = new EventWaitHandle(false, EventResetMode.AutoReset); static EventWaitHandle _go = new EventWaitHandle(false, EventResetMode.AutoReset); static readonly object _locker = new object(); static string _message; public static void main() { new Thread(Work).Start(); _ready.WaitOne(); //Espera hasta que el worker esté listo lock (_locker) _message = "ooo"; _go.Set(); // Le dice al worker que siga desde el hilo principal _ready.WaitOne(); lock (_locker) _message = "ahhh"; // Envía otro mensaje al worker desde el hilo principal _go.Set(); // Le dice al worker que se salga poniendo la variable _message en nulo lock (_locker) _message = null; } static void Work() while (true) _ready.Set(); // Indica al hilo principal que ya está listo _go.WaitOne(); // Espera señal del hilo principal para seguir lock (_locker) if (_message == null) return; //Se sale de este hilo Console.WriteLine(_message);

36 WaitAny, WaitAll, SignalAndWait
Aparte de los métodos Set(), WaitOne() y Reset(), la clase WaitHandle tiene los siguiente métodos estáticos: WaitAny: espera por cualquiera de los WaitHandle especificados. WaitAll: espera todos los WaitHandle especificados. SignalAndWait: llama set() en el primer WaitHandle especificado y llama WaitOne() en el segundo. Muy útil para coordinar señales entre 2 hilos.

37 Ejercicio #4 (Signaling)
El organismo de transito de la ciudad tiene una capacidad para 20 usuarios en su sala de espera, por lo que si llegan mas usuarios tienen que esperar afuera hasta que algun usuario sea atendido. Al llegar a la portería del tránsito, los usuarios son atendidos por un funcionario que les recibe los papeles para iniciar su tramite y los deja pasar en caso de haber espacio en la sala de espera o cuando lo haya. Una vez adentro de la sala de espera, la finalización del tramite dura 3 segundos antes de salir de la sala. Es necesario conocer cuando se temrinen de atender las primeras 40 personas. Represente la situación anterior en una rutina de .NET usando los conocimientos adquiridos en semaphores y signaling.

38 Referencias http://www.albahari.info/threading/threadin g.pdf
C3%B3n


Descargar ppt "Procesos e hilos Juan Camilo Jiménez Dorado"

Presentaciones similares


Anuncios Google