Estaba leyendo subprocesos múltiples en Java y me encontré con esto
Las variables locales son seguras para subprocesos en Java.
Desde entonces he estado pensando cómo / por qué las variables locales son seguras para subprocesos.
¿Alguien puede avisarme?
java
thread-safety
Anand
fuente
fuente
Respuestas:
Cuando creas un hilo, se creará su propia pila. Dos subprocesos tendrán dos pilas y un subproceso nunca comparte su pila con otro subproceso.
A todas las variables locales definidas en su programa se les asignará memoria en la pila (como comentó Jatin, memoria aquí significa, valor de referencia para objetos y valor para tipos primitivos) (Cada llamada al método por un hilo crea un marco de pila en su propia pila). Tan pronto como este hilo complete la ejecución del método, se eliminará el marco de pila.
Hay una gran conferencia del profesor de Stanford en youtube que puede ayudarlo a comprender este concepto.
fuente
Las variables locales se almacenan en la propia pila de cada hilo. Eso significa que las variables locales nunca se comparten entre hilos. Eso también significa que todas las variables primitivas locales son seguras para subprocesos.
public void someMethod(){ long threadSafeInt = 0; threadSafeInt++; }
Las referencias locales a objetos son un poco diferentes. La referencia en sí no se comparte. Sin embargo, el objeto al que se hace referencia no se almacena en la pila local de cada hilo. Todos los objetos se almacenan en el montón compartido. Si un objeto creado localmente nunca escapa al método en el que fue creado, es seguro para subprocesos. De hecho, también puede pasarlo a otros métodos y objetos siempre que ninguno de estos métodos u objetos haga que el objeto pasado esté disponible para otros subprocesos.
fuente
Piense en métodos como definiciones de funcionalidad. Cuando dos subprocesos ejecutan el mismo método, no están relacionados de ninguna manera. Cada uno creará su propia versión de cada variable local y no podrá interactuar entre sí de ninguna manera.
Si las variables no son locales (como las variables de instancia definidas fuera de un método en el nivel de clase), entonces se adjuntan a la instancia (no a una sola ejecución del método). En este caso, dos subprocesos que ejecutan el mismo método ven la única variable, y esto no es seguro para subprocesos.
Considere estos dos casos:
public class NotThreadsafe { int x = 0; public int incrementX() { x++; return x; } } public class Threadsafe { public int getTwoTimesTwo() { int x = 1; x++; return x*x; } }
En el primero, dos subprocesos que se ejecutan en la misma instancia de
NotThreadsafe
verán la misma x. Esto podría ser peligroso, porque los hilos están intentando cambiar x! En el segundo, dos subprocesos que se ejecutan en la misma instancia deThreadsafe
verán variables totalmente diferentes y no pueden afectarse entre sí.fuente
Cada invocación de método tiene sus propias variables locales y, obviamente, la invocación de un método ocurre en un solo hilo. Una variable que solo se actualiza mediante un único subproceso es inherentemente segura para subprocesos.
Sin embargo , esté atento a lo que se quiere decir exactamente con esto: solo las escrituras en la propia variable son seguras para subprocesos; llamar a métodos en el objeto al que hace referencia no es inherentemente seguro para subprocesos . Lo mismo ocurre con la actualización directa de las variables del objeto.
fuente
Además de las otras respuestas como la de Nambari.
Me gustaría señalar que puede usar una variable local en un método de tipo anónimo:
Este método podría invocarse en otros subprocesos que podrían comprometer la seguridad de los subprocesos, por lo que Java obliga a que todas las variables locales utilizadas en tipos anónimos se declaren como finales.
Considere este código ilegal:
public void nonCompilableMethod() { int i=0; for(int t=0; t<100; t++) { new Thread(new Runnable() { public void run() { i++; //compile error, i must be final: //Cannot refer to a non-final variable i inside an //inner class defined in a different method } }).start(); } }
Si java permitiera esto (como lo hace C # a través de "cierres"), una variable local ya no sería segura para subprocesos en todas las circunstancias. En este caso,
i
no se garantiza que el valor de al final de todos los hilos sea100
.fuente
El hilo tendrá su propia pila. Dos subprocesos tendrán dos pilas y un subproceso nunca comparte su pila con otro subproceso. Las variables locales se almacenan en la propia pila de cada hilo. Eso significa que las variables locales nunca se comparten entre hilos.
fuente
Básicamente, hay cuatro tipos de almacenamiento en java para almacenar información y datos de clase:
Área de método, montón, pila JAVA, PC
por lo tanto, el área de método y el montón son compartidos por todos los subprocesos, pero cada subproceso tiene su propia pila JAVA y PC y eso no es compartido por ningún otro subproceso.
Cada método en java es como marco de pila. entonces, cuando un método es llamado por un hilo, ese marco de pila se carga en su Pila JAVA. Todas las variables locales que están allí en ese marco de pila y la pila de operandos relacionados no son compartidas por otros. La PC tendrá información de la siguiente instrucción a ejecutar en el código de bytes del método. por lo que todas las variables locales son THREAD SAFE.
@Weston también ha dado una buena respuesta.
fuente
Solo las variables locales se almacenan en la pila de subprocesos.
La variable local que es
primitive type
(por ejemplo, int, long ...) se almacena en elthread stack
y, como resultado, otro hilo no tiene acceso a él.La variable local que es
reference type
(sucesora deObject
) contiene 2 partes: la dirección (que se almacena enthread stack
) y el objeto (que se almacena enheap
)class MyRunnable implements Runnable() { public void run() { method1(); } void method1() { int intPrimitive = 1; method2(); } void method2() { MyObject1 myObject1 = new MyObject1(); } } class MyObject1 { MyObject2 myObject2 = new MyObject2(); } class MyObject2 { MyObject3 myObject3 = MyObject3.shared; } class MyObject3 { static MyObject3 shared = new MyObject3(); boolean b = false; }
fuente