Situação:
Thread T precisa de um recurso R indisponível enquanto executa um método sincronizado.
Laços de sondagem não são ideais, pois bloqueiam o objeto, limitando o multitarefa.
Solução:
T abandona temporariamente o controle do objeto.
Outra thread pode ser executada enquanto T aguarda notificação para retomar.
Comunicação entre threads:
Usada para notificar e reativar threads bloqueadas.
Suporte em Java por meio dos métodos wait(), notify() e notifyAll().
Regras de uso:
Esses métodos pertencem à classe Object e devem ser usados dentro de blocos sincronizados.
wait() suspende a thread e libera o monitor para outra thread.
notify() reativa uma única thread em espera.
notifyAll() reativa todas as threads em espera (prioridade mais alta é executada).
Formas de wait():
wait() – espera indefinidamente até notificação.
wait(long millis) – espera por notificação ou até expirar o tempo especificado.
wait(long millis, int nanos) – espera com precisão de nanossegundos.
Cuidado com ativações falsas:
Chamadas a wait() podem ser ativadas por engano.
Recomendação: sempre verificar a condição esperada dentro de um laço.
Exemplo que usa wait( ) e notify( )
- Contexto: Criar um programa que simula o tique-taque de um relógio.
Classe principal:
Nome: TickTock.
Métodos:
tick(): Exibe a palavra "Tick".
tock(): Exibe a palavra "Tock".
Execução:
Duas threads são criadas:
Uma chama o método tick().
Outra chama o método tock().
Objetivo: Garantir a execução coordenada das threads para exibir um padrão coerente de "Tick" seguido por "Tock".
Classe principal (TickTock):
Contém dois métodos principais: tick() e tock().
Propósito: Garantir alternância entre "Tick" e "Tock".
Utiliza o campo state para armazenar o estado atual: "ticked" ou "tocked".
Execução em main():
Cria um objeto TickTock chamado tt.
Duas threads (Tick e Tock) são iniciadas, baseadas na classe MyThread.
Classe MyThread:
Recebe como argumentos:
O nome da thread ("Tick" ou "Tock").
Referência ao objeto TickTock (tt).
O método run() decide se chama tick() ou tock() com base no nome da thread.
Faz cinco chamadas aos métodos com true para mantê-los ativos.
Uma chamada final com false interrompe o relógio.
Mecanismo de sincronização:
Os métodos tick() e tock() de TickTock garantem a alternância usando o campo state e os métodos wait() e notify().
tick() espera que state seja "tocked" antes de avançar, e vice-versa em tock().
- tick() modificado com synchronized: Necessário porque wait() e notify() só podem ser usados em métodos sincronizados.
Parâmetro running: Controla o desligamento do relógio. Se running for false, tick() define state como "ticked", chama notify() e retorna.
Funcionamento normal:
Exibe "Tick".
Define state como "ticked".
Chama notify() para liberar outra thread que está esperando.
Entra em suspensão com wait(), aguardando que outra thread chame notify().
Laço while com wait():
Garante que wait() só continue quando state for "tocked".
Previne ativações falsas, que poderiam fazer a thread reiniciar incorretamente.
tock():
Similar a tick(), mas exibe "Tock" e define state como "tocked".
Mantém o sincronismo, alternando entre tick() e tock().
Chamada a notify() ao desligar:
Necessária para liberar threads que estão aguardando quando o relógio é interrompido.
Sem essa chamada, o programa pode "travar", pois uma thread aguardará indefinidamente.
Teste sem wait() e notify():
O programa não sincronizará corretamente o "Tick" e "Tock".
Resultado: Desordem na execução das mensagens.
Os métodos tick() e tock() não estão mais sincronizados entre si. Isso significa que eles podem ser executados independentemente, sem garantir que um "Tick" seja seguido por um "Tock" ou vice-versa.
Top comments (0)