2012-01-05 7 views
5

I cambiar un valor que se utiliza para determinar cuando un bucle while termina en un hilo separado.
No quiero saber cómo hacerlo funcionar. Si accedo a la prueba variable sólo a través sincronizados getters/setters funciona como se esperaba ..comportamiento extraño en Java con acceso unsyncronized en un programa de multihilo

lo que habría esperado, si algunos de escritura/lectura se pierden debido a la concurrencia el programa a veces no termina, pero nunca hace. Eso es lo que me confunde ..
Me gustaría saber por qué el programa nunca termina, sin la impresión de comandos. Y me gustaría entender por qué la impresión comando cambia nada ..

 

    public class CustomComboBoxDemo { 
     public static boolean test = true; 
     public static void main(String[] args) { 
      Thread user =new Thread(){ 
       @Override 
       public void run(){ 
        try { 
         sleep(2000); 
        } catch (InterruptedException e) {} 
        test=false; 
       } 
      }; 
      user.start(); 
      while(test) { 
       System.out.println("foo"); //Without this line the program does not terminate.. 
      } 
     } 
    } 

+0

Ver: [Loop no ve el valor cambiado sin una declaración impresa] (https://stackoverflow.com/questions/25425130/loop-doesnt-see-changed-value-without-a -print -statement) – Boann

Respuesta

8

La explicación más probable es que la variable solo se lee una vez, convirtiendo el while en un bucle infinito (o no-op). Como no ha declarado test como volatile, el compilador puede realizar dicha optimización.

Una vez que llama a una función externa desde el bucle, el compilador ya no puede probar que test permanece invariante en iteraciones de bucle y no realiza la optimización.

+1

Me pregunto, ¿es el compilador de bytecode o el compilador JIT el que hace ese tipo de optimización? – bezmax

+0

@Max: en mi sistema, el compilador de códigos de bytes no lo hace, por lo que tiene que ser el compilador JIT. – NPE

+1

Por cierto, también podría ser que esté constantemente leyéndolo, pero hacerlo desde un caché (como un registro de CPU) que no se ve afectado por la escritura en la memoria principal. Marcar el campo como 'volátil 'arreglará esto también. – yshavit

0

supongo que es algo que ver con la forma en que se maneja IO. Sin la impresión, probablemente verá la aplicación Java usando todo el tiempo de CPU disponible; con la impresión, es probable que las demoras de IO den tiempo suficiente para que se realice otro procesamiento.

Una forma rápida para poner a prueba esta teoría sería poner printlns en el método run() de su hilo para ver si el hilo está ejecutando en realidad nunca. En mi experiencia, infinitos bucles vacíos causan un comportamiento extraño.

Dicho esto, parece que termine bien en mi estación de trabajo bajo JDK 1.6.0_10_b23

+0

De acuerdo con mcfinnigan. Agregue algunas impresiones de depuración a su hilo. Cuando algo no funciona como se espera, siempre haz algo de trabajo para demostrar que tus suposiciones son correctas, en este caso, que el hilo por separado funciona según lo diseñado. – Mitch

1

Si la variable test no se define como volatile, el compilador probablemente optimiza el bucle que contiene ninguna operación en un bucle while(true) para su principal hilo y el programa nunca termina.

De lo contrario, el valor de la variable test se comprueba realmente y cuando su segunda cadena cambia su valor, la cadena principal sale del bucle while y su programa finaliza.

0

parece que su loop está siendo compilado incorrectamente lejos en un ocupado: espere. Agregar una palabra clave volátil a su booleano corrige el 'problema'.

0
public static boolean test = true; 
public static void main(String[] args) { 
    Thread user =new Thread(){ 
     @Override 
     public void run(){ 
      try { 
       sleep(2000); 
      } catch (InterruptedException e) {} 
      test=false; 
      System.out.println("Thread.end <"+test+">"); 
     } 
    }; 
    user.start(); 
    while(test); 
} 

Eso es interesante. El compilador probablemente optimice esto en un bucle sin fin, sin leer el valor en cada ciclo.

Definición de prueba como volatile reparar este problema y dejar que el programa termine

Por cierto: probablemente ya saben que deberían poner utiliza user.join() para esperar a que el Hilo para poner fin a

0

No entiendo lo que intenta hacer utilizando un código que sabe que no está sincronizado correctamente.

Como algunos han informado, en su máquina el código se comporta de forma diferente que en su máquina. El comportamiento del código mal sincronizado es undefined. No tiene sentido tratar de comprender lo que hace, ya que ese comportamiento cambiará con la versión o arquitectura de JVM.

Cuestiones relacionadas