"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Por que um thread sempre readquire o bloqueio de objeto após notify() ou notifyAll()?

Por que um thread sempre readquire o bloqueio de objeto após notify() ou notifyAll()?

Publicado em 2024-11-16
Navegar:611

Why Does One Thread Always Reacquire the Object Lock After notify() or notifyAll()?

A distinção sutil entre notify() e notifyAll()

Embora a principal diferença entre notify() e notifyAll() esteja no número de threads em espera que eles despertam (um contra todos), isso levanta outra questão:

Por que um thread sempre readquire o bloqueio do objeto?

Em geral Nesse caso, notify() e notifyAll() não especificam qual thread em espera será selecionado para readquirir o bloqueio. A JVM ou o agendador de thread do sistema faz essa seleção, que pode ser não determinística.

A necessidade de notifyAll()

No entanto, usar notify() em determinados cenários pode levar a um impasse, conforme ilustrado pelo exemplo a seguir:

Producer/Consumer Class with notify()

public class ProducerConsumer {

    private final int MAX_SIZE = 1;  // Buffer size

    private List buf = new ArrayList();

    public synchronized void put(Object o) {
        while (buf.size() == MAX_SIZE) {
            wait();
        }
        buf.add(o);
        notify();
    }

    public synchronized Object get() {
        while (buf.size() == 0) {
            wait();
        }
        Object o = buf.remove(0);
        notify();
        return o;
    }
}

Cenário de impasse:

  1. O produtor P1 coloca um objeto no buffer.
  2. Os produtores P2 e P3 tentam colocar objetos, mas não conseguem bloqueado porque o buffer está cheio.
  3. O consumidor C1 tenta obter um objeto do buffer.
  4. C1 está em execução e obtém o objeto e, em seguida, notifica um thread em espera.
  5. P2 ou C2 podem ser despertados pela notificação, mas ambos são bloqueados ao tentar readquirir o bloqueio.
  6. C3 também é bloqueado ao tentar adquirir o bloqueio.

Como um como resultado, todos os três threads estão aguardando indefinidamente, levando a um impasse. notify() no código do produtor/consumidor. Isso garante que todos os threads em espera sejam ativados, evitando deadlocks.

Recomendação:

Para a maioria dos cenários, notifyAll() é o método preferido, pois evita possíveis deadlocks. Se o cenário específico exigir a ativação de apenas um thread de espera específico, então notify() poderá ser usado com cautela.

Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3