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
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
x
e o outro vai para o monitor de objetos y
. Se um thread em um objeto x
tentar chamar qualquer método sincronizado no objeto y
, e o objeto y
ao mesmo tempo tentar chamar qualquer método sincronizado no objeto x
, os threads ficarão presos esperando. Abaixo 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:
- O que exatamente cada um dos threads em execução simultânea faz?
- Quais fechaduras são usadas?
Friend
: alphonse
e 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
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
O que mais ler: |
---|
Grupo de desenvolvedores Java: Otimizações SQL interessantes que não dependem do modelo de custo. Parte 1 |
GO TO FULL VERSION