JavaRush /Blogue Java /Random-PT /O que é impasse em Java?
Alexey Smirnov
Nível 29
Москва

O que é impasse em Java?

Publicado no grupo Random-PT
Nível de conhecimento necessário para entender o artigo: você concluiu as missões Java Syntax e Java Core e agora está aprendendo Java Multithreading. Deadlock ou impasse em Java ou impasse é um erro que ocorre quando threads têm uma dependência cíclica de um par de objetos sincronizados. Imagine que um thread vai para o monitor de objetos xe o outro vai para o monitor de objetos y. Se um thread em um objeto xtentar chamar qualquer método sincronizado no objeto y, e o objeto yao mesmo tempo tentar chamar qualquer método sincronizado no objeto x, os threads ficarão presos esperando. O que é impasse?  - 1Abaixo está um exemplo do tutorial do Java Docs sobre um conceito como impasse. Onde ocorre o bloqueio de threads aqui?
public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            @Override
            public void run() {
               // System.out.println("Thread 1");
                alphonse.bow(gaston);
               // System.out.println("Th: gaston bowed to alphonse");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
              //  System.out.println("Thread 2");
                gaston.bow(alphonse);
              //  System.out.println("2.gaston waiting alph bowed");
            }
        }).start();
    }
}
Há duas coisas importantes para entender aqui:
  1. O que exatamente cada um dos threads em execução simultânea faz?
  2. Quais fechaduras são usadas?
Vamos começar do fim. Digamos que você criou dois objetos da classe Friend: alphonsee gaston. Cada um deles possui seu próprio bloqueio. Assim, existem duas dessas fechaduras: gigolôs e gastons. Quando um método sincronizado de um objeto é inserido, seu bloqueio é bloqueado e, quando o método é encerrado, ele é liberado (ou desbloqueado). Agora sobre os tópicos. Vamos chamar o primeiro thread Alphonse(com letra maiúscula para distingui-lo do objeto alphonse). Aqui está o que ele faz (vamos chamá-lo de A, abreviação de Alphonse):
A: alphonse.bow(gaston) — получает лок alphonse;
A: gaston.bowBack(alphonse) — получает лок gaston;
A: возвращается из обоих методов, тем самым освобождая лок.
E aqui está o que o tópico está fazendo neste momento Gaston:
G: gaston.bow(alphonse) — получает лок gaston;
G: alphonse.bowBack(gaston) — получает лок alphonse;
G: возвращается из обоих методов, тем самым освобождая лок.
Agora vamos juntar esses dados e obter a resposta. Os threads podem ser interligados (ou seja, seus eventos ocorrerão) em ordens diferentes. Um impasse funcionará, por exemplo, se a ordem for a seguinte:
A: alphonse.bow(gaston) — получает лок alphonse
G: gaston.bow(alphonse) — получает лок gaston
G: пытается вызвать alphonse.bowBack(gaston), но блокируется, ожидая лока alphonse
A: пытается вызвать gaston.bowBack(alphonse), но блокируется, ожидая лока gaston
O que é impasse?  - 2
Nesse caso, ambos os threads estão bloqueados e cada um espera que o outro libere o bloqueio. Mas nenhum deles fará isso, pois para isso precisam completar seu método, e ele é bloqueado por outro thread. Então eles ficaram presos onde isso aconteceu deadlock. Porém, outra tecelagem também é possível, em que um dos fios terá tempo de se completar antes do início do segundo:
A: alphonse.bow(gaston) — получает лок alphonse
A: gaston.bowBack(alphonse) — получает лок gaston
A: возвращается из обоих методов, открывая оба лока
G: gaston.bow(alphonse) — получает лок gaston
G: alphonse.bowBack(gaston) — получает лок alphonse
G: возвращается из обоих методов, открывая оба лока
Neste caso, não há bloqueio mútuo de threads. Por exemplo, foi adicionado algum método que permite que outro thread tenha tempo para ser executado. Quando o resultado depende da ordem dos eventos que ocorrem simultaneamente (ordem planejada ou velocidade de execução), tal processo é chamado de condição de corrida em russo - “condição de corrida”. Nem todas as condições de corrida causam potencialmente um impasse; no entanto, na minha experiência, apenas as condições de corrida causam impasses. Respondido por: Dave Lillethun
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION