Java - Porque este programa no corre bien sin un sleep

 
Vista:

Porque este programa no corre bien sin un sleep

Publicado por Gabriel Castillo (6 intervenciones) el 19/10/2015 18:03:43
Hola, escribí un programa con treads que simula una línea de producción por cada Thread. Se tiene una variable de clase que lleva el numero de productos totales producidos por todas las líneas de producción. El programa debe terminar cuando se han producido 10 productos (se modifica la variable termina a true). El siguiente programa resuelve el problema pero... sólo si dejo el spleep del programa principal, si lo comentario el programa nunca termina o al menos termina mucho después de los 10. Sospecho que es un asunto de optimización, pero no estoy seguro, quisiera entender porque sucede esto ¿alguna idea? saludos


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class Linea extends Thread {
 
	static boolean termina = false;
	static int productosProducidosFabrica = 0;
 
	Linea(String Nombre) {
		super(Nombre);
	}
 
 
	public void run() {
		long t;
		try {
			while (!termina) {
				t = (long)(Math.random()*2000);
				sleep(t);
				if (!termina) {
					productosProducidosFabrica++;
					System.out.println(productosProducidosFabrica+":"+getName()+" produjo uno");
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
 
	}
}
 
 
public class Principal {
 
 
	public static void main(String[] args) throws InterruptedException {
		Linea lineaA, lineaB, lineaC;
		lineaA = new Linea("Linea A");
		lineaB = new Linea("Linea B");
		lineaC = new Linea("Linea C");
 
		lineaA.start();
		lineaB.start();
		lineaC.start();
 
		while (!Linea.termina) {
			Linea.termina = Linea.productosProducidosFabrica>=10;
			//Thread.sleep(500);	
 
		}
	}
 
}
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Porque este programa no corre bien sin un sleep

Publicado por Tom (1831 intervenciones) el 20/10/2015 10:14:50
Cuando haces esto:

1
2
3
while (!Linea.termina) {
			Linea.termina = Linea.productosProducidosFabrica>=10;
		}

estás usando todo el tiempo de CPU posible para el thread principal; los otros hilos estarán casi permanentemente "dormidos".

Además, debes proteger el acceso al atributo termina.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por Gabriel Castillo (6 intervenciones) el 20/10/2015 16:13:47
La respuesta no es tan simple. De hecho sucede exactamente lo contrario de lo que mencionas, si corres el programa obtendras:

1:Linea C produjo uno
2:Linea C produjo uno
3:Linea C produjo uno
4:Linea C produjo uno
5:Linea A produjo uno
6:Linea B produjo uno
7:Linea C produjo uno
8:Linea B produjo uno
9:Linea B produjo uno
10:Linea A produjo uno
11:Linea B produjo uno
12:Linea A produjo uno
13:Linea A produjo uno
14:Linea C produjo uno
15:Linea A produjo uno
16:Linea B produjo uno
etc...

Pareciera que no se ejecuta el hilo principal y que nunca se da cuenta que la variable de clase termina llega a ser mayor o igual a 10. El planificador impide de hecho que el hilo principal monopolice el procesador. Lo curioso es que si agrego el sleep(500) el programa funciona correctamente (se termina cuando se llega a una cuenta superior o igual a diez) aun cunado el sleep lo coloque en la cuenta minima de 1 ms (sleep(1))


Ya se que hay que hay que proteger el acceso a la variable, pero esta duda busca aclarar qué esta ocurriendo y porqué no se termina cuando no se tiene el sleep... es por asi decirlo (como decimos en México "un torito" para ver que tanto entendemos los conceptos...

¿algun valiente en el ruedo? :) saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por Tom (1831 intervenciones) el 20/10/2015 16:42:57
No. No es que suceda lo contrario, ni mucho menos.
Lo que ocurre es que no te das cuenta (y sí, quizás la jvm -que tú estás usando- "optimize" ese bucle para que no monopolice la CPU, y además, quizás, el S.O. añade su propio control, y quizás, otra jvm para otro S.O. o CPU o simplemente de otra versión no optimice o lo haga de otra manera).

Pon un simple println() en el bucle while y probablemente funcione igual que cuando pones el sleep. ¿ Que estás alterando el comportamiento del optimizador de la jvm ? Pues sí, pero allá tú si confías en saber cómo y cuando el compilador de java optimiza un bucle ...

En tu código hay más de un error y uno de ellos es la espera activa en tu thread principal.

Otro error es no declarar las variables necesarias como volatile. Ya que te preocupa, y conoces bien, el optimizador de la jvm, ten en cuenta eso. Imagino que sabes muy bien que cada hilo puede estar "viendo" un valor en caché del atributo termina en lugar del valor real (y esto puede permitir a la jvm obviar el bucle principal al considerar que Linea.termina no cambia).

Y otro es el no sincronizar la lectura e incremento de productosProducidosFabrica. Esto es "de primero de threads".

En resumen, el hecho de que tu programa parezca funcionar bien cuando pones el sleep es circunstancial. Simplemente no hay una única causa.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por Gabriel Castillo (6 intervenciones) el 20/10/2015 17:26:17
Gracias Tom,

Se que hay que sincronizar y entiendo lo del asunto de volatil, los he omitido intencionalmente. Lo que me comentas confirma mi suposicion, la espera activa es optimizada y probablemente obviada por el compilador, que simplemente asume que esta linea es inecesaria. Efectivamente si pones un printf corre correctamente.

Gracias por tu respuesta

saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por Gabriel Castillo (6 intervenciones) el 20/10/2015 17:45:28
Por cierto, con colocar como volatile la variable termina, el programa funciona aun con espera activa :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por Gabriel Castillo (6 intervenciones) el 20/10/2015 17:45:48
Por cierto, con colocar como volatile la variable termina, el programa funciona aun con espera activa :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por Tom (1831 intervenciones) el 20/10/2015 20:47:45
Sí, claro que termina tarde o temprano, tienes que marear mucho al planificador (de la jvm o del S.O) para que un hilo no reciba tiempo de CPU en absoluto.
Pero en un caso real, con docenas de hilos y procesos corriendo y proceso de verdad (no simples timeouts) se nota, y se nota mucho.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Lawliet
Val: 308
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

Porque este programa no corre bien sin un sleep

Publicado por Lawliet (303 intervenciones) el 20/10/2015 22:32:31
Hola...

Estoy ejecutando tu aplicación, y la salida que obtengo es la siguiente...

Captura

Esa salida que obtengo la consigo ya sea con el Sleep comentado o descomentado.

En pocas palabras... No le veo mucho sentido a tu programa, serías tan amable de explicarte bien que es lo que planeas para que de esa forma podamos ayudarte de mejor manera. Ya que por lo que eh probado, siempre termina, solo cambia el tiempo en que termina por el manejo de tus Sleep, pero por lo menos a mi nunca se cicla.

Sin mas que comentar, cualquier duda y/o inconveniente, aquí estamos. Suerte!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Porque este programa no corre bien sin un sleep

Publicado por gabriel Castillo (6 intervenciones) el 21/10/2015 16:07:32
El programa es un ejemplo muy simple, si lo quieres pensar como "de interés académico".

el punto es que la espera activa del hilo principal no funciona al menos en dos maquinas (windows 10, core i7, windows 7 core i5). Lo que deseo entender es por qué no funciona, me diras es que está mal escrito, pero creo que tener una explicación razonable de por qué esto no funciona ayuda a escribir mejores programas. Gracias por tu ayuda :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar