thread safety safe example español java multithreading thread-safety

java - example - thread safety php



¿Por qué esta clase no es segura para subprocesos? (7)

¿Alguien puede explicar por qué la clase anterior no es segura para subprocesos?

  • increment es estático, la sincronización se realizará en la propia clase.
  • decrement no es estático, la sincronización se realizará en la instanciación del objeto, pero eso no asegura nada ya que el count es estático

Me gustaría agregar que para declarar un contador seguro para subprocesos, creo que la forma más simple es usar AtomicInteger lugar de un int primitivo.

Permíteme redirigirte a la información del paquete java.util.concurrent.atomic .

class ThreadSafeClass extends Thread { private static int count = 0; public synchronized static void increment() { count++; } public synchronized void decrement() { count--; } }

¿Alguien puede explicar por qué la clase anterior no es segura para subprocesos?


  1. decrement es bloquear una cosa diferente para increment modo que no impidan que se ejecuten entre sí.
  2. Llamar decrement en una instancia es bloquear una cosa diferente a llamar decrement en otra instancia, pero están afectando lo mismo.

El primero significa que las llamadas superpuestas para increment y decrement podrían resultar en una cancelación (correcta), un incremento o una disminución.

El segundo significa que dos llamadas superpuestas para decrement en diferentes instancias podrían resultar en una doble disminución (correcta) o una sola disminución.


Como el método de increment es static , se sincronizará en el objeto de clase para ThreadSafeClass . El método de decrement no es estático y se sincronizará en la instancia utilizada para llamarlo. Es decir, se sincronizarán en diferentes objetos y, por lo tanto, dos hilos diferentes pueden ejecutar los métodos al mismo tiempo. Como las operaciones ++ y -- no son atómicas, la clase no es segura para subprocesos.

Además, dado que el count es static , modificarlo desde decrement que es un método de instancia sincronizada, no es seguro ya que se puede invocar en diferentes instancias y modificar el count simultáneamente de esa manera.


Como se explica en otras respuestas, su código no es seguro para subprocesos ya que el método estático increment() bloquea el monitor de clase y el método no estático decrement() bloquea el monitor de objetos.

Para este ejemplo de código, existe una mejor solución sin el uso synchronzed palabras clave. Tienes que usar AtomicInteger para lograr la seguridad de subprocesos.

Hilo seguro con AtomicInteger :

import java.util.concurrent.atomic.AtomicInteger; class ThreadSafeClass extends Thread { private static AtomicInteger count = new AtomicInteger(0); public static void increment() { count.incrementAndGet(); } public static void decrement() { count.decrementAndGet(); } public static int value() { return count.get(); } }


Dado que hay dos métodos diferentes, uno es el nivel de instancia y otro es el nivel de clase, por lo que debe bloquear 2 objetos diferentes para que sea ThreadSafe


Las respuestas de otros son bastante buenas, explican la razón. Solo agrego algo para resumir synchronized :

public class A { public synchronized void fun1() {} public synchronized void fun2() {} public void fun3() {} public static synchronized void fun4() {} public static void fun5() {} } A a1 = new A();

synchronized en fun1 y fun2 se sincroniza a nivel de objeto de instancia. synchronized en fun4 se sincroniza a nivel de objeto de clase. Lo que significa:

  1. Cuando 2 hilos llaman a a1.fun1() al mismo tiempo, se bloqueará la última llamada.
  2. Cuando el subproceso 1 llame a a1.fun1() y el subproceso 2 llame a a1.fun2() al mismo tiempo, se bloqueará la última llamada.
  3. Cuando el subproceso 1 llama a a1.fun1() y el subproceso 2 llama a a1.fun3() al mismo tiempo, sin bloqueo, los 2 métodos se ejecutarán al mismo tiempo.
  4. Cuando el hilo 1 llame a A.fun4() , si otros hilos llaman a A.fun4() o A.fun5() al mismo tiempo, las últimas llamadas se bloquearán ya que synchronized en fun4 es el nivel de clase.
  5. Cuando el hilo 1 llama a A.fun4() , el hilo 2 llama a a1.fun1() al mismo tiempo, sin bloqueo, los 2 métodos se ejecutarán al mismo tiempo.

Tiene dos métodos sincronizados, pero uno de ellos es estático y el otro no. Al acceder a un método sincronizado, basado en su tipo (estático o no estático), se bloqueará un objeto diferente. Para un método estático, se colocará un bloqueo en el objeto Clase, mientras que para el bloque no estático, se colocará un bloqueo en la instancia de la clase que ejecuta el método. Debido a que tiene dos objetos bloqueados diferentes, puede tener dos hilos que modifiquen el mismo objeto simultáneamente.