1
resposta

[Dúvida] Dúvida sobre syncronized(this) quando utilizado em apenas um dos métodos.

Olá! Para ver como o syncronized(this) funciona, comentei ele no segundo método para ver o que iria acontecer:

package br.com.alura.banheiro.principal;

public class Banheiro {
    public void fazerNumero1() {
        String nome = Thread.currentThread().getName() + " ";
        
        System.out.println(nome + "batendo na porta");
        
        synchronized(this) {
            System.out.println(nome + "entrando no banheiro");
            System.out.println(nome + "fazendo coisa rápida");
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(nome + "dando descarga");
            System.out.println(nome + "lavando a mão");
            System.out.println(nome + "saindo do banheiro");
        }
    }
    public void fazerNumero2() {
        String nome = Thread.currentThread().getName() + " ";
        System.out.println(nome + "batendo na porta");
        //synchronized(this) {
        System.out.println(nome + "entrando no banheiro");
        System.out.println(nome + "fazendo coisa demorada");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(nome + "dando descarga");
        System.out.println(nome + "lavando a mão");
        System.out.println(nome + "saindo do banheiro");
        //}
    }
}

Maria é do método 1 e João é do método 2.

No programa principal, Maria chamou a tarefa primeiro e João depois:

package br.com.alura.banheiro.principal;

public class Principal {

    public static void main(String[] args) {
        
        Banheiro banheiro = new Banheiro();
        Thread thread1 = new Thread(new TarefaNumero1(banheiro), "Maria");
        Thread thread2 = new Thread(new TarefaNumero2(banheiro), "João");
        thread1.start();
        thread2.start();
    }

}

Só que o primeiro método (Maria) está com syncronized(this). Então eu achei que o thread da Maria iria executar o método inteiro de forma atômica, para só depois executar o thread do João; mas quando rodei o o programa Principal, uma thread 'esbarrou' na outra.

O resultado foi esse:

Maria batendo na porta
Maria entrando no banheiro
Maria fazendo coisa rápida
João batendo na porta
João entrando no banheiro
João fazendo coisa demorada
Maria dando descarga
Maria lavando a mão
Maria saindo do banheiro
João dando descarga
João lavando a mão
João saindo do banheiro

A minha dúvida é por quê é necessário utilizar syncronized(this) nos dois métodos (fazerNumero1() e fazerNumero2()) se o syncronized faz o código dentro dele ser executado do início ao fim?

1 resposta

Olá! Entendo que a situação pode parecer um pouco confusa, mas vou tentar esclarecer.

A palavra-chave synchronized em Java é usada para controlar o acesso a um bloco de código ou método por múltiplas threads. Quando você usa synchronized(this), você está dizendo que apenas uma thread pode acessar o bloco de código sincronizado por vez.

No seu exemplo, você tem dois métodos na classe Banheiro: fazerNumero1() e fazerNumero2(). Cada um desses métodos representa uma ação diferente que pode ser realizada no banheiro. Quando você usa synchronized(this) em apenas um dos métodos, você está basicamente dizendo: "apenas uma thread pode 'fazerNumero1()' por vez, mas várias threads podem 'fazerNumero2()' ao mesmo tempo".

Então, no seu caso, mesmo que Maria (que está usando o método fazerNumero1()) tenha chamado a tarefa primeiro, João (que está usando o método fazerNumero2()) não precisa esperar Maria terminar para começar a sua tarefa, pois o método fazerNumero2() não está sincronizado.

Se você quiser que apenas uma thread possa usar o banheiro por vez, independentemente de estar "fazendo número 1" ou "fazendo número 2", você precisará usar synchronized(this) em ambos os métodos. Isso garantirá que, mesmo que Maria e João tentem usar o banheiro ao mesmo tempo, um terá que esperar o outro terminar antes de poder começar.

Espero ter ajudado e bons estudos!