Comportamiento del método estático en un entorno de subprocesos múltiples en java

114

Hay una pregunta simple y estúpida que me molesta y hace varios argumentos en mi mente. Quiero descartar todas las dudas sobre las siguientes preguntas.

class Clstest{

    public static String testStaticMethod(String inFileStr) {

        // section 0

        // section 1

        // do something with inFileStr

        // section 2

        // section 3

        return inFileStr;

    }

}

Supongamos que hay cinco subprocesos que están ejecutando una llamada al Clstest.testStaticMethod("arg-n")mismo tiempo.

Llamadas del hilo 1 Clstest.testStaticMethod("arg-1").

Cuando el hilo 1 está en la sección 1, el hilo 2 llama Clstest.testStaticMethod("arg-2").

Entonces, ¿qué pasará con el hilo 1? ¿Pasará al estado de reposo?

Cuando el Thread 1 tenga la oportunidad, ¿reanudará la ejecución desde la sección 1 donde se detuvo?

¿Cómo sucede cuando se comparte uno Clstest.testStaticMethody el mismo Clstest.testStaticMethodentre los cinco hilos?

¿Existe la posibilidad de intercambiar el inFileStrenviado por múltiples hilos?

namalfernandolk
fuente
¿A qué idioma se dirige?
ΩmegaMan
3
@ OmegaMan: es java
namalfernandolk

Respuestas:

192

La respuesta de Hans Passant es buena. Pero pensé en intentar explicarlo en un nivel un poco más simple para cualquiera que se encuentre con esto y sea nuevo en Java. Aquí va..

La memoria en Java se divide en dos tipos: el montón y las pilas. El montón es donde viven todos los objetos y las pilas son donde los hilos hacen su trabajo. Cada hilo tiene su propia pila y no puede acceder a las pilas de los demás. Cada hilo también tiene un puntero en el código que apunta al bit de código que están ejecutando actualmente.

Cuando un hilo comienza a ejecutar un nuevo método, guarda los argumentos y las variables locales de ese método en su propia pila. Algunos de estos valores pueden ser punteros a objetos en el montón. Si dos subprocesos están ejecutando el mismo método al mismo tiempo, ambos tendrán sus punteros de código apuntando a ese método y tendrán sus propias copias de argumentos y variables locales en sus pilas. Solo interferirán entre sí si las cosas en sus pilas apuntan a los mismos objetos en el montón. En cuyo caso podrían suceder todo tipo de cosas. Pero como señala Hans, las cadenas son inmutables (no se pueden cambiar), así que estamos seguros si este es el único objeto que se "comparte".

Muchos subprocesos pueden ejecutar el mismo método. Es posible que no se estén ejecutando al mismo tiempo; depende de cuántos núcleos tenga en su máquina, ya que la JVM asigna subprocesos de Java a subprocesos del sistema operativo, que están programados en subprocesos de hardware. Por lo tanto, tiene poco control sobre la forma en que estos hilos se entrelazan sin utilizar mecanismos de sincronización complejos .

Tenga en cuenta que dormir es algo que un hilo se hace a sí mismo.

selig
fuente
3
Entonces, en un entorno de procesador de múltiples núcleos, puede haber varios subprocesos que ejecutan el mismo código al mismo tiempo, ¿no es así? Y en un entorno de procesador único, solo hay un hilo ejecutándose en un momento dado. (varios subprocesos que comparten el tiempo entre ellos). Entonces, cuando el programador del subproceso da la oportunidad del subproceso actual en ejecución (A) al subproceso (B), ¿cómo se reanuda el subproceso (A) desde donde se pausó? Quiero decir, ¿cómo sabe el punto de reanudación? ¿Se debe a que "cada hilo también tiene un puntero en el código que apunta al fragmento de código que están ejecutando actualmente?" ¿como dijiste?
namalfernandolk
6
Tu lo tienes. Solo para aclarar algunos puntos: en primer lugar, la forma en que se programan los subprocesos está fuera del control de Java. Estoy hablando de Sun's Hotspot JVM aquí. La JVM mapea un subproceso de Java a un subproceso del sistema operativo y el sistema operativo decide qué subprocesos ejecutar. Como usted dice, en una máquina de un solo núcleo, el sistema operativo solo puede ejecutarse uno a la vez, pero en una máquina multinúcleo puede ejecutar más de uno a la vez. En segundo lugar, un hilo no es realmente consciente de cuándo se pone en pausa, la única información que tiene es el puntero del programa (el puntero en el código) y la pila, que se guardan y restauran exactamente como estaban.
selig
Entonces, ¿la interferencia entre subprocesos ocurre cuando los subprocesos usan variables fuera de su alcance local y, por ejemplo, un subproceso actualiza el valor de la variable antes de que otro subproceso extraiga esa variable (o puntero a la variable) en su propia pila? ¿Es eso un entendimiento correcto?
hariszhr
2
Para ser un poco más precisos ... la interferencia solo puede ocurrir y puede ocurrir, pero no necesariamente sucederá ... cuando los hilos comparten cosas en el montón (no local). Hay algunas formas diferentes en las que pueden ocurrir interferencias que dependen de las dependencias entre las diferentes partes del código. No estoy seguro de su ejemplo, ya que faltan algunos detalles. Quizás se esté refiriendo a un problema potencial en el que los subprocesos A y B leen un valor compartido y luego lo actualizan en función del valor leído. Esta es una carrera de datos.
selig
1
@selig si tengo una clase con solo métodos de instancia, por ejemplo: una clase de servicio y es singleton, entonces no necesito preocuparme por varios subprocesos que ejecutan los métodos de instancia a la vez, ya que la clase de servicio no tiene ningún estado donde el estado está presente solo si la clase tiene variables de instancia. ¿Mi comprensión es correcta?
Yug Singh
67

¿Pasará al estado de reposo?

No, ejecutar un hilo no afecta a otros hilos siempre que no se sincronicen intencionadamente entre sí. Si tiene más de un núcleo de procesador, todas las máquinas recientes lo tienen, es probable que esos subprocesos se ejecuten exactamente al mismo tiempo. Eso es un poco menos probable cuando inicia 5 subprocesos, ya que es posible que su máquina no tenga suficientes núcleos. El sistema operativo se ve obligado a elegir entre ellos, dándoles algo de tiempo para que se ejecuten. El trabajo del programador de subprocesos. Entonces, un hilo no estará en un estado de "suspensión", simplemente estará en pausa y esperando que el programador del hilo le dé la oportunidad de ejecutarse. Se reanudará donde fue interrumpido por el programador.

¿Existe alguna posibilidad de intercambiar el inFileStr enviado por varios subprocesos?

No existe tal posibilidad, los subprocesos tienen su propia pila, por lo que cualquier argumento de método y variable local será único para cada subproceso. Además, el uso de una cadena garantiza que estos hilos no puedan interferir entre sí, ya que las cadenas son inmutables.

No existe tal garantía si el argumento es una referencia a otro tipo de objeto mutable. O si el método en sí usa variables que son estáticas o referencias a objetos en el montón. La sincronización es necesaria cuando un hilo modifica el objeto y otro hilo lo lee. La palabra clave de bloqueo en el lenguaje C # es la forma estándar de implementar dicha sincronización requerida. El hecho de que el método sea estático no significa que dicha sincronización nunca sea necesaria. Es menos probable, ya que no tiene que preocuparse de que los hilos accedan al mismo objeto (compartir esto ).

Hans Passant
fuente
3
Vaya, nunca vi la etiqueta [java]. Suficientemente cerca.
Hans Passant
Olvidé agregar cuando se publicó. Culpa mía. :). De todas formas gracias por la respuesta. Fue muy útil.
namalfernandolk