Pular para o conteúdo principal
Documentos
Palavras-chave JavaMatrizes JavaProgramação orientada a objetos em JavaManuseio de arquivos JavaIntrodução ao JavaNoções básicas da linguagem Java

palavra-chave synchronized em Java

A palavra-chave synchronized em Java controla o acesso a recursos compartilhados entre vários threads. Ele garante que somente um thread possa executar um bloco ou método sincronizado por vez, evitando a interferência de threads e garantindo a consistência da memória.

Uso

A palavra-chave synchronized pode ser aplicada a métodos ou blocos dentro de métodos. Quando um método ou bloco é declarado como sincronizado, um bloqueio é obtido no objeto especificado, e outros threads são impedidos de acessar o código sincronizado até que o bloqueio seja liberado.

Sintaxe

Método sincronizado

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

Bloco sincronizado

public void method() {
    synchronized (object) {
        // synchronized code
    }
}
  • object: O objeto no qual você deseja sincronizar. Normalmente, essa é a instância atual (this) ou um objeto específico.

Exemplos

Exemplo 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());
    }
}

Neste exemplo, o método increment é sincronizado, garantindo que somente um thread possa incrementar o contador por vez, evitando condições de corrida.

Exemplo 2: Bloco 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 exemplo usa um bloco sincronizado para controlar o acesso à variável count. O objeto de bloqueio garante que somente um thread possa executar o bloco sincronizado por vez.

Dicas e práticas recomendadas

  • Minimizar o código sincronizado: Mantenha os blocos sincronizados tão curtos quanto possível para reduzir a contenção e melhorar o desempenho.
  • Use Final Objects: Ao usar blocos sincronizados, use objetos finais como bloqueios para garantir a consistência.
  • Evite a sincronização aninhada: Os blocos sincronizados aninhados podem levar a deadlocks. Evite-os ou use-os com cautela.
  • Use coleções simultâneas: Para uma sincronização complexa, considere o uso de coleções simultâneas do pacote java.util.concurrent, como ConcurrentHashMap, que oferece sincronização integrada.
  • Volatile Keyword: Para variáveis que são acessadas por vários threads, mas que não exigem sincronização complexa, considere usar a palavra-chave volatile para garantir a visibilidade.
private volatile boolean flag;
  • Segurança da linha: Certifique-se sempre de que os recursos compartilhados estejam devidamente sincronizados para manter a segurança do thread e evitar a corrupção de dados.
  • Métodos estáticos sincronizados: Sincronize métodos estáticos para impor o acesso sincronizado no nível da classe, garantindo que apenas um thread possa executar o método estático em todas as instâncias.
public static synchronized void staticMethod() {
    // method code
}
  • Reentrada: Os bloqueios intrínsecos do Java são reentrantes, o que significa que, se um thread mantiver um bloqueio, ele poderá adquiri-lo novamente sem entrar em um deadlock.

Learn Java Essentials

Desenvolva suas habilidades em Java desde o início e domine os conceitos de programação.
Comece a aprender de graça