Palavra-chave synchronized em Java

A palavra-chave synchronized em Java é usada para garantir que um bloco de código ou um método seja acessado por apenas um thread por vez. Isso é essencial em ambientes multithread para evitar condições de corrida e garantir a integridade dos dados quando múltiplos threads podem acessar recursos compartilhados simultaneamente.

Uso da Palavra-chave synchronized

1.Método Synchronized: Ao declarar um método como synchronized, você garante que apenas um thread possa executar esse método em um objeto específico ao mesmo tempo. O lock é obtido no objeto em que o método é chamado.

public class ContaBancaria {
    private int saldo;

    public synchronized void depositar(int valor) {
        saldo += valor;
    }

    public synchronized void sacar(int valor) {
        saldo -= valor;
    }

    public synchronized int getSaldo() {
        return saldo;
    }
}

2.Bloco Synchronized: Às vezes, você pode querer sincronizar apenas uma parte do código dentro de um método. Nesse caso, você usa um bloco synchronized. Isso pode ser mais eficiente do que sincronizar o método inteiro, pois o lock é aplicado apenas à parte crítica do código.

public class ContaBancaria {
    private int saldo;

    public void depositar(int valor) {
        synchronized (this) {
            saldo += valor;
        }
    }

    public void sacar(int valor) {
        synchronized (this) {
            saldo -= valor;
        }
    }

    public int getSaldo() {
        synchronized (this) {
            return saldo;
        }
    }
}

3.Synchronized em Blocos com Objetos: Você também pode sincronizar em um objeto diferente, o que pode ser útil para evitar a sincronização de todo o método ou classe.

public class ContaBancaria {
    private int saldo;
    private final Object lock = new Object();

    public void depositar(int valor) {
        synchronized (lock) {
            saldo += valor;
        }
    }

    public void sacar(int valor) {
        synchronized (lock) {
            saldo -= valor;
        }
    }

    public int getSaldo() {
        synchronized (lock) {
            return saldo;
        }
    }
}

Comportamento e Regras

  • Locks e Monitores: Quando um método ou bloco é sincronizado, ele adquire um lock no objeto especificado (ou na classe se o método for estático). Enquanto o lock está em uso, outros threads são impedidos de acessar qualquer método ou bloco sincronizado no mesmo objeto até que o lock seja liberado.
  • Deadlock: Se não for usado com cuidado, a sincronização pode levar a deadlocks, onde dois ou mais threads estão bloqueados indefinidamente esperando uns pelos outros liberarem locks.
  • Desempenho: O uso excessivo ou inadequado de synchronized pode levar a problemas de desempenho, pois pode criar contenção entre threads e reduzir a concorrência.

Exemplo de Uso

Aqui está um exemplo básico mostrando como a sincronização pode ser usada para evitar condições de corrida em um contador simples:

public class Contador {
    private int count = 0;

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

    public synchronized int getCount() {
        return count;
    }

    public static void main(String[] args) {
        Contador contador = new Contador();

        // Criar vários threads para incrementar o contador
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                contador.incrementar();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                contador.incrementar();
            }
        });

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

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

        System.out.println("Contador: " + contador.getCount());
    }
}




No exemplo acima, a sincronização garante que os métodos incrementar e getCount sejam acessados de forma segura por múltiplos threads, prevenindo problemas de concorrência e garantindo um resultado correto.