Que escribí siguiente código para entender el concepto volátil en java, pero la salida parece estar confundiendo más que aclarar el concepto. Correcciones, aclaraciones y comentarios son bienvenidos y apreciados.
package threading;
public class UnSyncRead {
//volatile static int value = 987;
static int value = 987;
public static void main(String[] args) {
ThreadEx4 t = new ThreadEx4(value);
t.start();
for(int i=0;i<4;i++) {
Thread thread = new Thread( new ThreadEx3(value));
thread.start();
}
}
}
class ThreadEx3 implements Runnable{
private int i;
public ThreadEx3(int i) {
this.i=i;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+ " "+Thread.currentThread().getName()+" "+ " inside "+i);
}
}
class ThreadEx4 extends Thread{
private int i;
public ThreadEx4(int i) {
this.i=i;
}
public void run() {
++i;
System.out.println("changed the value to "+i);
}
}
Este programa da la siguiente salida
changed the value to 988
12 Thread-1 inside 987
13 Thread-2 inside 987
14 Thread-3 inside 987
15 Thread-4 inside 987
pero si puedo modificar el código para hacer value
la variable volatile
haciendo siguiente cambio y ejecutar el código.
public class UnSyncRead {
volatile static int value = 987;
//static int value = 987;
public static void main(String[] args) {
ThreadEx4 t = new ThreadEx4(value);
t.start();
for(int i=0;i<4;i++) {
Thread thread = new Thread( new ThreadEx3(value));
thread.start();
}
}
}
Consigo siguiente salida, que es exactamente lo mismo cuando me encontré con él sin palabra clave volátil.
changed the value to 988
12 Thread-1 inside 987
13 Thread-2 inside 987
14 Thread-3 inside 987
15 Thread-4 inside 987
Mi pregunta es por qué los hilos en el bucle todavía están leyendo el valor de la value
variable como 987
no 988
, incluso después de la aplicación de la palabra clave volátil.
Apreciarán profundamente respuesta a este problema.
Esto no tiene nada que ver con múltiples hilos en absoluto, es una cuestión mucho más fundamental.
class ThreadEx4 extends Thread{
private int i;
public ThreadEx4(int i) {
this.i=i;
}
public void run() {
++i;
System.out.println("changed the value to "+i);
}
}
Está cambiando la variable privada i
aquí, no lo global static
campo.
Java pasa a las cosas por su valor. Así, cuando decimos new ThreadEx4(myInteger)
, el constructor recibirá el interior varios myInteger
. Sea lo que hace a su copia local no afecta myInteger
en absoluto.
Para continuar con los experimentos multi-threading, deshacerse de las variables locales y hacer
class Ex4 extends Runnable {
@Override
public void run(){
int newValue = ++UnSyncRead.value;
System.out.println("changed the value to "+newValue);
}
}
// and the same for the other runnables