Multi hilos o Multi threads
Tanto java como .Net proveen soporte para multihilos.
Ambos corren con un hilo principal (ejecutado por el main) y desde aqui en adelante se pueden crear hilos hijos, workers, y aqui el el programa se vuelve multithread.
Los procesos separados (workers) corren en distintos pedazos de memoria (del stack)
y son dos instancias distintas.
Se puede compartir datos entre ellos por ejemplo con variables estaticas, pero hay que tener mucho cuidado porque la modificacion de uno puede afectar al desempeño del otro.
Esto se llama concurrencia, y para que esto no afecte, se puede loquear la modificacion/lectura de la variable.
Vamos con un ejemplo.
clase CajeroAutomatico{
Cuenta unaCuentaBancaria;
funcion ExtraerDinero(Double cantidad){
if (unaCuentaBancaria.dineroDisponible > cantidad ){
unaCuentaBancaria.dineroDisponible = unaCuentaBancaria.dineroDisponible -cantidad;
}
}
}
El procesamiento de los hilos (manejando los tiempos de procesador que le otorga el sistema operativo a cada hilo) puede dedicarle el tiempo que crea necesario a cada hilo, y frenarlo cuando tambien lo quiera. Esto no lo podemos controlar nosotros porque depende de todo lo que esta corriendo en la pc en ese momento.
Suponiendo que vieje Pepe Argento al cajero, y decide sacar $900 de su cuenta que tiene $ 1000.
entra al método ExtraerDinero , entra al if, y el sistema operativo descide frenar por un momento la ejecución de este programa antes de sacar dinero, para darle un rato de procesador a otro programa.
Sabrina Rojas (mujer de el :) ) descide ir y sacar $500 de dinero de la misma cuenta, y el SO le otorga un rato de procesador a ella (a su programa)
Pero a diferencia del otro, no lo frena dentro del if, sino que sigue y extrae
ahora el SO , vuelve a darle tiempo al proceso frenado anteriormente (frenado justo antes de sacar) y quiere extraer.
Que paso aca?
la cuenta tenia $ 1000.
Sabrina saco $500 (qdan $500)
pepe quiere sacar $900 , Esto reventaria en algun lado , ya que faltan $400.
El problema fue la concurrencia sobre la variable "dineroDisponible" .
para ello toda la ejecucion del método, o mas concreto, del if , debería estar loqueada.
algo asi como
lock {
if (...){...}
}
Con esto, El SO sabe que
NO debe frenar el proceso dentro del lock ( o sea en el if)
de esta manera, Sabrina no podria entrar a la condición del if, ya que cuando salga del if de pepe quedaran $100.
ejemplo c#
class ThreadTest {
static void Main() {
Thread t = new Thread (WriteY);
t.Start(); // Run WriteY on the new thread
while (true) Console.Write ("x"); // Write 'x' forever
}
static void WriteY() {
while (true) Console.Write ("y"); // Write 'y' forever
}
}
sacado de
http://www.albahari.com/threading/index.html#_Introduction ahi veriamos como le asigna ("aleatoriamente") tiempo a cada uno de los procesos.
la salida seria algo asi
yyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxyyyyyyyyy
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxyyyyy
xxxxxxxxxxxxxx
(un rato a cada uno)
Java:
En Java para la creacion de hilos, se hereda de la clase Thread Java aplica aqui el patrón Template.
La clase Thread es abstracta e implementa la interfaz Runeable, que tiene el metodo run();
Nos provee métodos para:
start() : Este metodo ejecutara el metodo run() implementado por nosotros (aqui esta el patrón template)
isAlive() : True si el hilo esta corriendo
sleep(N) : Duerme al hilo N milisegundos
interrupt() : Pide al hilo que se interrumpa (InterrumpedException si estaba en sleep)
isInterrupted() : True si esta interrumpido
priority : Prioridad del hilo (No conviene abusar de esto a menos que se sepa bien lo que se hace)
yield() : El hilo deja su ejecucion para darle lugar al siguiente. la proxima vez que le toque se ejecutara
join() : El hilo actual se queda esperando hasta que el hilo que llamo al join termine su ejecucion y nuestra clase hija,
Sacado de Algoritmos 3 (Fontela FIUBA)
Para crear un hilo:
class HiloConcreto extends Thread {
public void run() {
... código del hilo ...
}
...
}
...
HiloConcreto unHilo = new HiloConcreto();
unHilo.start(); // start llama a run de manera polimorfa
DotNet C#
A diferencia de Java, c# aplica el patrón Command, donde se le pasa “Un puntero a función” del método a ejecutar.
Usamos el namespace
using System.Threading;
y en main por ejemplo
Thread unHiloWorker = new Thread(new ThreadStart(metodoAEjecutar));
unHiloWorker.Start();
Donde Start() ejecutara el metodo que le hayamos pasado (aqui el patron command)