Saltar al contenido principal
Documentos
Java keywordsMatrices JavaProgramación orientada a objetos en JavaJava File HandlingIntroducción a JavaConceptos básicos del lenguaje Java

sincronizado Palabra clave en Java

La palabra clave synchronized en Java controla el acceso a los recursos compartidos entre varios subprocesos. Garantiza que sólo un hilo pueda ejecutar un bloque o método sincronizado a la vez, evitando interferencias entre hilos y asegurando la coherencia de la memoria.

Utilización

La palabra clave synchronized puede aplicarse a métodos o bloques dentro de métodos. Cuando un método o bloque se declara como sincronizado, se obtiene un bloqueo sobre el objeto especificado, y se bloquea el acceso de otros hilos al código sincronizado hasta que se libere el bloqueo.

Syntax

Método sincronizado

public synchronized void synchronizedMethod() {
    // method code
}

Bloque sincronizado

public void method() {
    synchronized (object) {
        // synchronized code
    }
}
  • object: El objeto sobre el que sincronizar. Suele ser la instancia actual (this) o un objeto concreto.

Ejemplos

Ejemplo 1: Método sincronizado

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        Counter counter = new Counter();

        // Create multiple threads to increment the counter
        Thread t1 = new Thread(() -> counter.increment());
        Thread t2 = new Thread(() -> counter.increment());

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + counter.getCount());
    }
}

En este ejemplo, el método increment está sincronizado, lo que garantiza que sólo un hilo puede incrementar el contador a la vez, evitando condiciones de carrera.

Ejemplo 2: Bloque sincronizado

public class SynchronizedBlockExample {
    private final Object lock = new Object();
    private int count = 0;

    public void increment() {
        synchronized (lock) {
            count++;
        }
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        SynchronizedBlockExample example = new SynchronizedBlockExample();

        // Create multiple threads to increment the counter
        Thread t1 = new Thread(() -> example.increment());
        Thread t2 = new Thread(() -> example.increment());

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final count: " + example.getCount());
    }
}

Este ejemplo utiliza un bloque sincronizado para controlar el acceso a la variable count. El objeto de bloqueo garantiza que sólo un hilo pueda ejecutar el bloque sincronizado a la vez.

Consejos y buenas prácticas

  • Minimizar el Código Sincronizado: Mantén los bloques sincronizados lo más cortos posible para reducir la contención y mejorar el rendimiento.
  • Utiliza Objetos Finales: Cuando utilices bloques sincronizados, utiliza objetos finales como bloqueos para garantizar la coherencia.
  • Evita la Sincronización Anidada: Los bloques sincronizados anidados pueden provocar bloqueos. Evítalos o utilízalos con precaución.
  • Utiliza Colecciones Concurrentes: Para una sincronización compleja, considera la posibilidad de utilizar colecciones concurrentes del paquete java.util.concurrent, como ConcurrentHashMap, que proporcionan sincronización incorporada.
  • Palabra clave volátil: Para las variables a las que acceden varios subprocesos pero que no requieren una sincronización compleja, considera la posibilidad de utilizar la palabra clave volatile para garantizar la visibilidad.
private volatile boolean flag;
  • Seguridad de la rosca: Asegúrate siempre de que los recursos compartidos están correctamente sincronizados para mantener la seguridad de los hilos y evitar la corrupción de datos.
  • Métodos estáticos sincronizados: Sincroniza los métodos estáticos para imponer el acceso sincronizado a nivel de clase, garantizando que sólo un hilo pueda ejecutar el método estático en todas las instancias.
public static synchronized void staticMethod() {
    // method code
}
  • Reentrada: Los bloqueos intrínsecos de Java son reentrantes, lo que significa que si un hilo tiene un bloqueo, puede adquirirlo de nuevo sin bloquearse.

Aprende Java Essentials

Desarrolla tus conocimientos de Java desde la base y domina los conceptos de programación.
Empieza a aprender gratis