java - operacion - operadores logicos
Valor de retorno del operador de asignación en código concurrente (3)
Dada la siguiente clase:
class Foo {
public volatile int number;
public int method1() {
int ret = number = 1;
return ret;
}
public int method2() {
int ret = number = 2;
return ret;
}
}
y dado que hay múltiples hilos llamando al method1()
y al method2()
al mismo tiempo en la misma instancia de Foo
, ¿puede una llamada a method1 () devolver algo que no sea 1?
Creo que la respuesta depende del compilador. El lenguaje specifies :
En tiempo de ejecución, el resultado de la expresión de asignación es el valor de la variable una vez que se ha realizado la asignación.
Supongo que teóricamente el valor podría cambiarse antes de que ocurra la segunda asignación (la más a la izquierda).
Sin embargo, con el compilador javac de Sun, method1
se convertirá en:
0: aload_0
1: iconst_1
2: dup_x1
3: putfield #2; //Field number:I
6: istore_1
7: iload_1
8: ireturn
Esto duplica la constante 1
en la pila y la carga en number
y luego en ret
antes de devolver ret
. En este caso, no importará si el valor almacenado en number
se modifica antes de la asignación a ret
, porque 1
, no se está asignando un número.
El JLS 15.26 especifica:
Hay 12 operadores de asignación; todos son sintácticamente correctos (se agrupan de derecha a izquierda). Por lo tanto, a = b = c significa a = (b = c), que asigna el valor de c a b y luego asigna el valor de b a a.
La respuesta de Ted Hopp muestra que el javac de Sun no sigue este comportamiento, posiblemente como una optimización.
Debido al enhebrado aquí, el comportamiento del método1 no estaría definido. Si el compilador de Sun hace que el comportamiento sea constante, entonces no se rompe del comportamiento indefinido.
O la instrucción contiene una lectura volátil, o no contiene una lectura volátil. Aquí no puede haber ambigüedad, ya que la lectura volátil es muy importante para la semántica del programa.
Si se puede confiar en javac, podemos concluir que el enunciado no implica una lectura volátil del number
. El valor de una expresión de asignación x=y
es realmente el valor de y
(después de las conversiones).
También podemos deducir eso
System.out.println(number=1);
no implica leer el number
String s;
(s="hello").length();
no implica leer
x_1=x_2=...x_n=v
no implica leer x_n, x_n-1, ...
; en cambio, el valor de v
se asigna directamente a x_i
(después de las conversiones necesarias a través de los tipos de x_n, ... x_i