O que é um impasse?

159

Ao escrever aplicativos multithread, um dos problemas mais comuns encontrados são os impasses.

Minhas perguntas à comunidade são:

  1. O que é um impasse?

  2. Como você os detecta?

  3. Você lida com eles?

  4. E, finalmente, como você evita que elas ocorram?

bmurphy1976
fonte

Respostas:

206

Um bloqueio ocorre quando vários processos tentam acessar o mesmo recurso ao mesmo tempo.

Um processo perde e deve esperar o outro terminar.

Um impasse ocorre quando o processo de espera ainda está retendo outro recurso que o primeiro precisa antes de concluir.

Então, um exemplo:

O recurso A e o recurso B são usados ​​pelo processo X e pelo processo Y

  • X começa a usar A.
  • X e Y tentam começar a usar B
  • Y 'vence' e recebe B primeiro
  • agora Y precisa usar A
  • A está bloqueado por X, que está aguardando Y

A melhor maneira de evitar conflitos é evitar que os processos se cruzem dessa maneira. Reduza a necessidade de bloquear tudo o que puder.

Nos bancos de dados, evite fazer muitas alterações em tabelas diferentes em uma única transação, evite gatilhos e alterne para leituras otimistas / sujas / nolock o máximo possível.

Keith
fonte
9
Estou usando o processo aqui como uma generalização, não especificamente como um processo do sistema operacional. Podem ser threads, mas também podem ser aplicativos completamente diferentes ou conexões com o banco de dados. O padrão é o mesmo.
Keith
1
Olá, dado esse cenário: o segmento A bloqueia o recurso A e possui um processo longo. O segmento B espera para bloquear o recurso A. Uso do tempo da CPU: 20%, você pode considerar uma situação de conflito?
precisa saber é o seguinte
2
@rickyProgrammer não, isso é apenas uma espera regular de bloqueio, embora a diferença seja um pouco acadêmica. B aguardando devagar A é um bloqueio, B aguardando A aguardando B é um impasse.
Keith
Então impasse é mais de dois processos com recursos bloqueados à espera de que esses recursos sejam liberados ..
rickyProgrammer
2
@rickyProgrammer, é um bloqueio que não será liberado, não importa quanto tempo você espere, devido à fila circular.
Keith
126

Deixe-me explicar um exemplo do mundo real (não realmente real) para uma situação de impasse nos filmes de crime. Imagine que um criminoso mantém um refém e, contra isso, um policial também mantém um refém amigo do criminoso. Nesse caso, o criminoso não vai deixar o refém ir se o policial não deixar o amigo deixar ir. Além disso, o policial não vai deixar o amigo do criminoso soltar, a menos que o criminoso libere o refém. Esta é uma situação infindável e sem fim, porque os dois lados estão insistindo no primeiro passo um do outro.

Cena criminal e policial

insira a descrição da imagem aqui

Então, simplesmente, quando dois encadeamentos precisam de dois recursos diferentes e cada um deles possui o bloqueio do recurso que o outro precisa, é um impasse.

Outra explicação de alto nível do impasse: corações partidos

Você está namorando com uma garota e, um dia depois de uma discussão, ambos os lados estão com o coração partido e esperando uma ligação que eu sinto muito e perdi . Nessa situação, os dois lados querem se comunicar se, e somente se, um deles recebe uma ligação do outro, desculpe-me . Como nenhum dos dois iniciará a comunicação e a espera em um estado passivo, ambos esperarão que o outro inicie a comunicação que acaba em uma situação de impasse.

Levent Divilioglu
fonte
Se os threads pertencerem a processos diferentes?, Os segmentos pertencentes ao mesmo processo também podem causar um impasse?
lordvcs
1
@diabolicfreak Não importa se os threads pertencem ao mesmo processo ou não.
Sam Malayek 15/05/19
2
Outro exemplo da vida real poderia ser quatro carros chegando ao cruzamento de duas estradas iguais em quatro direções simultaneamente. Todos precisam dar passagem a um carro pelo lado direito, para que ninguém possa prosseguir.
LoBo 28/07/19
35

Os deadlocks só ocorrerão quando você tiver dois ou mais bloqueios que podem ser adquiridos ao mesmo tempo e eles forem agarrados em ordem diferente.

As formas de evitar conflitos são:

  • evitar bloqueios (se possível),
  • evite ter mais de um bloqueio
  • sempre feche as fechaduras na mesma ordem.
Mats Fredriksson
fonte
O terceiro ponto para evitar um impasse (sempre use os bloqueios na mesma ordem) é vital, o que é bastante fácil de ser esquecido na prática de codificação.
Qiang Xu
20

Para definir deadlock, primeiro eu definiria processo.

Processo : Como sabemos, processo não passa de um programem execução.

Recurso : para executar um processo do programa, são necessários alguns recursos. As categorias de recursos podem incluir memória, impressoras, CPUs, arquivos abertos, unidades de fita, CD-ROMS, etc.

Deadlock : Deadlock é uma situação ou condição em que dois ou mais processos estão mantendo alguns recursos e tentando adquirir mais recursos, e eles não podem liberar os recursos até que concluam a execução.

Condição ou situação de impasse

insira a descrição da imagem aqui

No diagrama acima, existem dois processos P1 e p2 e existem dois recursos R1 e R2 .

O recurso R1 é alocado para o processo P1 e o recurso R2 é alocado para o processo p2 . Para concluir a execução do processo, o P1 precisa do recurso R2 , portanto, o P1 solicita o R2 , mas o R2 já está alocado para o P2 .

Da mesma forma, o Processo P2 para concluir sua execução precisa de R1 , mas R1 já está alocado para P1 .

ambos os processos não podem liberar seus recursos até e a menos que concluam sua execução. Então, ambos estão esperando por outros recursos e esperarão para sempre. Portanto, esta é uma condição DEADLOCK .

Para que o conflito ocorra, quatro condições devem ser verdadeiras.

  1. Exclusão mútua - Cada recurso está atualmente alocado em exatamente um processo ou está disponível. (Dois processos não podem controlar simultaneamente o mesmo recurso ou estar em sua seção crítica).
  2. Espera e espera - os processos que atualmente mantêm recursos podem solicitar novos recursos.
  3. Sem preempção - Depois que um processo retém um recurso, ele não pode ser retirado por outro processo ou pelo kernel.
  4. Espera circular - Cada processo está aguardando para obter um recurso mantido por outro processo.

e todas essas condições são satisfeitas no diagrama acima.

Varun
fonte
8

Um impasse ocorre quando um encadeamento está aguardando algo que nunca ocorre.

Normalmente, isso acontece quando um encadeamento está aguardando um mutex ou semáforo que nunca foi liberado pelo proprietário anterior.

Também acontece frequentemente quando você tem uma situação envolvendo dois threads e dois bloqueios como este:

Thread 1               Thread 2

Lock1->Lock();         Lock2->Lock();
WaitForLock2();        WaitForLock1();   <-- Oops!

Você geralmente os detecta porque as coisas que você espera que nunca aconteçam, ou o aplicativo trava completamente.

17 de 26
fonte
Um impasse ocorre quando um encadeamento está aguardando algo que não pode ocorrer.
Marquês de Lorne
4

Você pode dar uma olhada nesses artigos maravilhosos , na seção Deadlock . Está em C #, mas a ideia ainda é a mesma para outra plataforma. Cito aqui para facilitar a leitura

Um conflito ocorre quando dois encadeamentos esperam por um recurso mantido pelo outro, portanto nenhum deles pode prosseguir. A maneira mais fácil de ilustrar isso é com dois bloqueios:

object locker1 = new object();
object locker2 = new object();

new Thread (() => {
                    lock (locker1)
                    {
                      Thread.Sleep (1000);
                      lock (locker2);      // Deadlock
                    }
                  }).Start();
lock (locker2)
{
  Thread.Sleep (1000);
  lock (locker1);                          // Deadlock
}
onmyway133
fonte
4

O impasse é um problema comum nos problemas de multiprocessamento / multiprogramação no SO. Digamos que existem dois processos P1, P2 e dois recursos compartilháveis ​​globalmente R1, R2 e, na seção crítica, ambos os recursos precisam ser acessados

Inicialmente, o sistema operacional atribui R1 ao processo P1 e R2 ao processo P2. Como ambos os processos estão em execução simultaneamente, eles podem começar a executar seu código, mas o PROBLEMA surge quando um processo atinge a seção crítica. Portanto, o processo R1 aguardará o processo P2 liberar R2 e vice-versa ... Então, eles aguardarão para sempre (CONDIÇÃO DE DELOCK).

Uma pequena ANALOGIA ...

Sua mãe (OS),
você (P1),
seu irmão (P2),
maçã (R1),
faca (R2),
seção crítica (cortar maçã com faca).

Sua mãe lhe dá a maçã e a faca para seu irmão no começo.
Ambos estão felizes e brincando (Executando seus códigos).
Qualquer um de vocês deseja cortar a maçã (seção crítica) em algum momento.
Você não quer dar a maçã ao seu irmão.
Seu irmão não quer dar a faca para você.
Então vocês dois vão esperar por muito, muito tempo :)

Rohit Singh
fonte
2

O impasse ocorre quando dois threads adquirem bloqueios que impedem que um deles progrida. A melhor maneira de evitá-los é com um desenvolvimento cuidadoso. Muitos sistemas embarcados se protegem contra eles usando um cronômetro de vigilância (um cronômetro que redefine o sistema sempre que for interrompido por um determinado período de tempo).

Joseph Sturtevant
fonte
2

Um impasse ocorre quando há uma cadeia circular de encadeamentos ou processos, cada um contendo um recurso bloqueado e tentando bloquear um recurso retido pelo próximo elemento da cadeia. Por exemplo, dois encadeamentos que mantêm respectivamente o bloqueio A e o bloqueio B e estão tentando adquirir o outro bloqueio.

Marquês de Lorne
fonte
Eu voto em você. Sua resposta é mais concisa do que acima, porque eles causam um conflito confuso por processo ou thread. Algum processo digamos um, alguns um segmento digamos :)
hainguyen
1

Um programa clássico e muito simples para entender a situação de Deadlock : -

public class Lazy {

    private static boolean initialized = false;

    static {
        Thread t = new Thread(new Runnable() {
            public void run() {
                initialized = true;
            }
        });

        t.start();

        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        System.out.println(initialized);
    }
}

Quando o thread principal chama Lazy.main, ele verifica se a classe Lazy foi inicializada e começa a inicializar a classe. O encadeamento principal agora define inicializado como false, cria e inicia um encadeamento em segundo plano cujo método de execução define inicializado como true e aguarda a conclusão do encadeamento em segundo plano.

Desta vez, a classe está sendo inicializada por outro thread. Nessas circunstâncias, o thread atual, que é o thread de segundo plano, aguarda o objeto Class até a inicialização ser concluída. Infelizmente, o encadeamento que está iniciando, o encadeamento principal, aguarda a conclusão do encadeamento em segundo plano. Como os dois threads agora estão esperando um pelo outro, o programa está DEADLOCKED.

Vivek Pratap Singh
fonte
0

Um impasse é um estado de um sistema no qual nenhum processo / encadeamento é capaz de executar uma ação. Conforme mencionado por outros, um impasse geralmente é o resultado de uma situação em que cada processo / encadeamento deseja adquirir um bloqueio para um recurso que já está bloqueado por outro (ou mesmo o mesmo) processo / encadeamento.

Existem vários métodos para encontrá-los e evitá-los. Um está pensando muito e / ou tentando muitas coisas. No entanto, lidar com o paralelismo é notoriamente difícil e a maioria (se não todas) as pessoas não serão capazes de evitar completamente os problemas.

Alguns métodos mais formais podem ser úteis se você levar a sério esse tipo de problema. O método mais prático que tenho conhecimento é usar a abordagem teórica do processo. Aqui você modela seu sistema em alguma linguagem de processo (por exemplo, CCS, CSP, ACP, mCRL2, LOTOS) e usa as ferramentas disponíveis para (modelar) verificar se há impasses (e talvez outras propriedades também). Exemplos de conjunto de ferramentas a serem usados: FDR, mCRL2, CADP e Uppaal. Algumas almas corajosas podem até provar seus sistemas livres de impasse usando métodos puramente simbólicos (prova de teoremas; procure Owicki-Gries).

No entanto, esses métodos formais normalmente exigem algum esforço (por exemplo, aprender o básico da teoria do processo). Mas acho que isso é simplesmente uma conseqüência do fato de que esses problemas são difíceis.

Mweerden
fonte
0

O impasse é uma situação que ocorre quando há menos número de recursos disponíveis, conforme solicitado pelo processo diferente. Isso significa que, quando o número de recursos disponíveis se torna menor do que o solicitado pelo usuário, nesse momento o processo entra em condição de espera. Algumas vezes a espera aumenta mais e não há chance de verificar o problema da falta de recursos. essa situação é conhecida como impasse. Na verdade, o deadlock é um grande problema para nós e ocorre apenas no sistema operacional multitarefa. O deadlock não pode ocorrer no sistema operacional de tarefa única porque todos os recursos estão presentes apenas para a tarefa que está sendo executada no momento ......

puja bharti
fonte
0

Acima algumas explicações são legais. Espero que isso também seja útil: https://ora-data.blogspot.in/2017/04/deadlock-in-oracle.html

Em um banco de dados, quando uma sessão (por exemplo, ora) deseja um recurso mantido por outra sessão (por exemplo, dados), mas essa sessão (dados) também deseja um recurso que é mantido pela primeira sessão (ora). Também pode haver mais de 2 sessões envolvidas, mas a ideia será a mesma. Na verdade, os deadlocks impedem que algumas transações continuem funcionando. Por exemplo: Suponha que ORA-DATA mantenha o bloqueio A e solicite o bloqueio B E o SKU mantenha o bloqueio B e solicite o bloqueio A.

Obrigado,

Sapna
fonte
0

O impasse ocorre quando um encadeamento aguarda a conclusão de outro encadeamento e vice-versa.

Como evitar?
- Evitar bloqueios aninhados
- Evitar bloqueios desnecessários
- Usar junção de thread ()

Como você o detecta?
execute este comando no cmd:

jcmd $PID Thread.print

referência : geeksforgeeks

Arun Raaj
fonte
0

Os conflitos não ocorrem apenas com bloqueios, embora essa seja a causa mais frequente. No C ++, você pode criar um deadlock com dois threads e sem bloqueios, basta ter cada chamada de thread join () no objeto std :: thread do outro.

Raghav Navada
fonte
0

Controle de simultaneidade baseado em bloqueio

O uso do bloqueio para controlar o acesso a recursos compartilhados é propenso a conflitos, e o planejador de transações sozinho não pode impedir suas ocorrências.

Por exemplo, os sistemas de banco de dados relacional usam vários bloqueios para garantir propriedades ACID da transação .

Não importa qual sistema de banco de dados relacional você esteja usando, os bloqueios sempre serão adquiridos ao modificar (por exemplo, UPDATEou DELETE) um determinado registro da tabela. Sem bloquear uma linha que foi modificada por uma transação em execução no momento, o Atomicity seria comprometido .

O que é um impasse

Como expliquei neste artigo , um conflito ocorre quando duas transações simultâneas não podem progredir porque cada uma espera a outra liberar uma trava, conforme ilustrado no diagrama a seguir.

insira a descrição da imagem aqui

Como as duas transações estão na fase de aquisição de bloqueio, nenhuma delas libera um bloqueio antes de adquirir o próximo.

Recuperando de uma Situação de Impasse

Se você estiver usando um algoritmo de controle de simultaneidade que depende de bloqueios, sempre haverá o risco de executar em uma situação de conflito. Os conflitos podem ocorrer em qualquer ambiente de simultaneidade, não apenas em um sistema de banco de dados.

Por exemplo, um programa de multithreading pode travar se dois ou mais threads estiverem aguardando bloqueios adquiridos anteriormente para que nenhum thread possa progredir. Se isso acontecer em um aplicativo Java, a JVM não poderá forçar apenas um Thread a interromper sua execução e liberar seus bloqueios.

Mesmo que a Threadclasse exponha um stopmétodo, esse método foi preterido desde o Java 1.1 porque pode fazer com que os objetos sejam deixados em um estado inconsistente após a interrupção de um encadeamento. Em vez disso, Java define um interruptmétodo, que age como uma dica, pois um encadeamento interrompido pode simplesmente ignorar a interrupção e continuar sua execução.

Por esse motivo, um aplicativo Java não pode se recuperar de uma situação de deadlock, e é responsabilidade do desenvolvedor do aplicativo ordenar as solicitações de aquisição de bloqueio de forma que os deadlocks nunca ocorram.

No entanto, um sistema de banco de dados não pode impor uma determinada ordem de aquisição de bloqueios, pois é impossível prever quais outros bloqueios uma determinada transação desejará adquirir ainda mais. Preservar a ordem de bloqueio passa a ser responsabilidade da camada de acesso a dados, e o banco de dados só pode ajudar na recuperação de uma situação de conflito.

O mecanismo do banco de dados executa um processo separado que verifica o gráfico de conflito atual em busca de ciclos de espera por bloqueio (causados ​​por conflitos). Quando um ciclo é detectado, o mecanismo de banco de dados escolhe uma transação e a interrompe, fazendo com que seus bloqueios sejam liberados, para que a outra transação possa progredir.

Diferentemente da JVM, uma transação de banco de dados é projetada como uma unidade atômica de trabalho. Portanto, uma reversão deixa o banco de dados em um estado consistente.

Para mais detalhes sobre este tópico, consulte este artigo também.

Vlad Mihalcea
fonte
-2

O Mutex, em essência, é um bloqueio, fornecendo acesso protegido a recursos compartilhados. No Linux, o tipo de dados mutex do encadeamento é pthread_mutex_t. Antes de usar, inicialize-o.

Para acessar recursos compartilhados, você deve bloquear o mutex. Se o mutex já estiver bloqueado, a chamada bloqueará o encadeamento até que o mutex seja desbloqueado. Após a conclusão da visita aos recursos compartilhados, você deverá desbloqueá-los.

No geral, existem alguns princípios básicos não escritos:

  • Obtenha o bloqueio antes de usar os recursos compartilhados.

  • Segurando a trava o mais curto possível.

  • Solte a trava se o encadeamento retornar um erro.

Marcus Thornton
fonte
3
Isso descreve um bloqueio, não um impasse.
Marquês de Lorne