Voy a iniciar mis andanzas en este blog con un tema complicado, la concurrencia.
La concurrencia en Java o en cualquier otro lenguaje es siempre un problema. Y lo es porque empiezas a jugar con unas reglas y según avanza la partida las reglas cambian, o eso es lo que parece. Porque el principal problema que enfrentamos cuando estamos codificando un proceso de forma que se ejecute con varios hilos simultáneos es el más temido entre los programadores: no poder reproducir la situación.
Realmente, ese es el resultado final, traído simplemente para escenificar el problema inicial, que no siempre se tiene en cuenta, las condiciones de ejecución de tu programa van a cambiar la forma de responder de tu código. Es culpa de lo que se conoce como condición de carrera: el resultado depende del orden en que se ejecuten los procesos concurrentes.
A lo largo de nuestra carrera profesional, muchos hemos pasado por el fantástico momento del mantenimiento correctivo de la aplicación. Es el momento en el que haces penitencia por los pecados cometidos durante el desarrollo. El momento en que te acuerda de aquello de «listo, esto funciona, subiendoooooo (a svn)». Que gracioso parecía hace unos meses, antes de que se produjese este error imposible, «lexe que 1+1 son 2 de toda la vida y ahora resulta que mi programa dice que son 2433453222».
En mantenimiento correctivo, el primer paso es «reproduce la incidencia». Pues te pones y resulta que no hay forma. Aquí viene en ayuda tuya lo que piensas del usuario. Y rechazas la incidencia. Pero la incidencia vuelve y esta vez con el fichero de trazas «JGL: después de calcular: a = 1, b=1, a+b = 3556122654». Mientras te estás frotando los ojos, pasa el listo de turno y te dice «eso va a ser el multithreading«…
Luego viene aquello de esto lo hemos probado mil veces…en una maquina aunque solo tiene un solo core y con un conjunto (reducido) de datos generados por nosotros.
Y es que esa es una característica de la concurrencia, el resultado depende del orden de ejecución de los hilos y este orden varía según el hardware y las entradas que tengamos. Tenemos un sistema que funciona perfectamente en una maquina con un dual core y que recibe 20 entradas por minuto, se traslada a una maquina con 4 cpu y 8 cores cada una porque el trafico va a multiplicarse por 50. Y ahora el sistema es diferente, el orden de ejecución de los hilos ha cambiado radicalmente. Por esto, por las condiciones de carrera, es necesario sincronizar nuestros hilos para que no se pisen unos a otros.
Para poder hacerlo necesitamos conocer las reglas y necesitamos mecanismos que garanticen que un hilo no rompe lo que hace otro y además que el cambio de hilo sea visible al resto. a=a+b no se realiza en un solo paso. En el punto en que nos afecta, primero se hace a+b y después se hace a = esa suma. Para garantizar que se hace en un solo paso, tenemos los mecanismos que vamos a ver en los próximos artículos.
Van a ser una serie de artículos en los que iremos viendo diferentes mecanismos que nos van a permitir controlar procesos que se ejecuten mediante hilos.
Esta serie va a estar dividida en 4 bloques:
- Lo básico
- Las circunstancias particulares
- Controlando la madeja
- Deshaciendo los nudos
Además, iré al lio, prometo no enrollarme. Nos vemos. Aquí.