Para que serve o método Syncronized?

Olá, estou estudando Java faz algum tempo, é, estou em dúvida num método que vi o meu professor usar. O método Syncronized. Para que serve? Ficarei agradecido quem me ajudar!

synchronized não é um método, é uma palavra-chave que pode ser aplicada a métodos. Ex:

// método sincronizado
public synchronized void fazAlgo() {
    // faz algo...
}

// método não sincronizado
public void fazAlgo2() {
    // faz algo...
}

A ideia é que um método sincronizado de um mesmo objeto não pode ser executado por 2 threads ao mesmo tempo. Para dar um exemplo, vamos supor que tenho essa classe:

public class Tarefa {
    public void fazAlgo() {
        System.out.println("fazendo algo...");
        try {
            // espera 2 segundos (para simular que está fazendo algo demorado)
            Thread.sleep(2000);
        } catch (InterruptedException ex) {}
        System.out.println("fim");
    }
}

Ela só imprime algumas mensagens, e fica 2 segundos parada (para simular alguma tarefa demorada). Agora vamos criar várias threads que chamam este método, para o mesmo objeto:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class SynchTest {
    public static void main(String[] args) throws Exception {
        // cria um pool de 5 threads
        int qtdThreads = 5;
        ExecutorService pool = Executors.newFixedThreadPool(qtdThreads);

        // adiciona as threads no pool
        Tarefa tarefa = new Tarefa();
        for (int i = 0; i < qtdThreads; i++) {
            pool.submit(() -> tarefa.fazAlgo());
        }
        // espera terminar
        pool.awaitTermination(2 * qtdThreads, TimeUnit.SECONDS);
    }
}

A saída será algo do tipo:

fazendo algo...
fazendo algo...
fazendo algo...
fazendo algo...
fazendo algo...
fim
fim
fim
fim
fim

Obs: pode ser que as saídas fiquem misturadas também (uma termine no meio, etc), já que threads não são determinísticas e a ordem não é garantida.

Isso acontece porque, enquanto uma das threads está no sleep, outra thread pode começar a executar (mesmo que seja o mesmo método do mesmo objeto).

Agora se eu mudar o método fazAlgo para ser sincronizado:

public class Tarefa {
    // *** agora o método é synchronized ***
    public synchronized void fazAlgo() {
        System.out.println("fazendo algo...");
        try {
            // espera 2 segundos (para simular que está fazendo algo demorado)
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
        }
        System.out.println("fim");
    }
}

A saída será:

fazendo algo...
fim
fazendo algo...
fim
fazendo algo...
fim
fazendo algo...
fim
fazendo algo...
fim

Pois agora, como o método é sincronizado, só uma thread pode executá-lo por vez. Então todas as outras threads tem que esperar a thread atual terminar, para só depois chamar o método de novo.


Claro que o assunto (threads, sincronização, etc) é bem mais complexo que isso, e um bom ponto de partida é este tutorial.

4 curtidas

CARA MUITO OBRIGADO, vc me salvou!