Eu gostaria de explicar os bloqueios de threading para iniciantes. Já vi muitos exemplos de deadlocks no passado, alguns usando código e outros usando ilustrações (como os famosos 4 carros ). Existem também problemas clássicos de fácil impasse, como The Dining Philosophers , mas eles podem ser complexos demais para um verdadeiro novato compreender totalmente.
Estou procurando o exemplo de código mais simples para ilustrar o que são deadlocks. O exemplo deve:
- Relacione-se com um cenário de programação "real" que faz algum sentido
- Seja muito curto, simples e direto
O que você recomenda?
multithreading
language-agnostic
deadlock
Roee Adler
fonte
fonte
Respostas:
Talvez uma situação bancária simples.
Obviamente, se houver duas threads que tentam executar a transferência ( a, b ) e a transferência ( b, a ) ao mesmo tempo, um deadlock ocorrerá porque elas tentam adquirir os recursos na ordem inversa.
Este código também é ótimo para procurar soluções para o impasse. Espero que isto ajude!
fonte
sync
pode ser algo como:sync(Account & a) { a.mutex.lock(); }
.Deixe a natureza explicar o impasse,
Impasse: Frog vs. Snake
fonte
Aqui está um exemplo de código do departamento de ciência da computação de uma universidade em Taiwan, mostrando um exemplo simples em java com bloqueio de recursos. Isso é muito relevante para a "vida real" para mim. Código abaixo:
fonte
Se method1 () e method2 () serão chamados por dois ou mais threads, há uma boa chance de deadlock porque se thread 1 adquirir bloqueio no objeto String durante a execução do método1 () e thread 2 adquirir bloqueio no objeto Integer durante a execução do método2 () ambos estarão esperando um ao outro para liberar o bloqueio de Integer e String para prosseguir, o que nunca acontecerá.
fonte
Um dos exemplos de impasse simples que encontrei.
fonte
private int index
fazendo aí?Aqui está um exemplo simples em C ++ 11.
fonte
Por favor, veja minha resposta a esta pergunta . Resultado final, sempre que dois threads precisam adquirir dois recursos diferentes, e o fazem em ordens diferentes, você pode obter impasses.
fonte
Um exemplo em que posso pensar é o cenário Mesa, Lanterna e Baterias. Imagine uma lanterna e um par de baterias colocados em cima de uma mesa. Se você fosse até esta mesa e pegasse as baterias enquanto outra pessoa está com a lanterna, vocês dois seriam forçados a se olharem sem jeito enquanto esperam por quem colocará seu item de volta na mesa. Este é um exemplo de impasse. Você e a pessoa estão esperando por recursos, mas nenhum de vocês está desistindo de seus recursos.
Da mesma forma, em um programa, o deadlock ocorre quando dois ou mais threads (você e a outra pessoa) estão esperando que duas ou mais travas (lanterna e baterias) sejam liberadas e as circunstâncias no programa são tais que as travas nunca são liberadas ( vocês dois têm uma peça do quebra-cabeça).
Se você conhece java, é assim que pode representar esse problema:
Se você executar este exemplo, notará que às vezes as coisas funcionam bem e corretamente. Mas às vezes seu programa simplesmente não imprime nada. Isso porque uma pessoa está com as pilhas e outra com a lanterna, o que impede que acendam a lanterna causando um travamento.
Este exemplo é semelhante ao exemplo dado pelos tutoriais java: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Outro exemplo é o exemplo de loop:
Este exemplo pode imprimir 'Não feito' repetidamente ou nunca pode imprimir 'Não feito'. O primeiro acontece porque o primeiro thread adquire o bloqueio de classe e nunca o libera, evitando que 'stopLoop' seja acessado pelo segundo thread. E o mais recente acontece porque o segundo encadeamento foi iniciado antes do primeiro encadeamento, fazendo com que a variável 'concluído' fosse verdadeira antes de o primeiro encadeamento ser executado.
fonte
fonte
No entanto, considero o problema dos Dining Philosophers um dos exemplos mais simples em mostrar impasses, uma vez que os 4 requisitos de impasse podem ser facilmente ilustrados pelo desenho (especialmente a espera circular).
Considero os exemplos do mundo real muito mais confusos para o novato, embora não consiga pensar em um bom cenário do mundo real de cabeça agora (sou relativamente inexperiente com simultaneidade no mundo real).
fonte
Recentemente percebi que as brigas entre casais não passam de um impasse .. onde normalmente um dos processos tem que travar para resolvê-lo, é claro que é o de menor prioridade (Menino;)).
Aqui está a analogia ...
Processo1: Menina (G) Processo2: Menino (B) Recurso1: Desculpe Recurso2
: Aceitando o próprio erro
Condições necessárias:
1. Exclusão mútua: Apenas um de G ou B pode pedir desculpas ou aceitar o próprio erro de cada vez.
2. Hold and Wait: Em um momento, um está segurando Desculpe e outro Aceitando o próprio erro, um está esperando Aceitando o próprio erro para liberar desculpe, e outro está aguardando desculpas para liberar aceitando o próprio erro.
3. Sem preempção: Nem mesmo Deus pode forçar B ou G a liberar Desculpe ou Aceitar o próprio erro. E voluntariamente? Você está brincando comigo??
4. Espera circular: Mais uma vez, aquele que está segurando o arrependimento espera que o outro aceite os próprios erros, e um que está segurando aceita os próprios erros quer que o outro se desculpe primeiro. Portanto, é circular.
Portanto, os impasses ocorrem quando todas essas condições estão em vigor ao mesmo tempo, e esse é sempre o caso em uma briga de casal;)
Fonte: http://www.quora.com/Saurabh-Pandey-3/Posts/Never-ending-couple-fights-a-deadlock
fonte
Mais um exemplo de deadlock simples com dois recursos diferentes e dois encadeamentos aguardando um ao outro para liberar o recurso. Diretamente de examples.oreilly.com/jenut/Deadlock.java
fonte
If all goes as planned, deadlock will occur, and the program will never exit.
Podemos fazer este exemplo deguarantee
deadlock?O impasse pode ocorrer em uma situação em que um
Girl1
está querendo flertar comGuy2
quem é pego por outroGirl2
eGirl2
quer flertar com umGuy1
que é pego porGirl1
. Visto que ambas as meninas estão esperando para se livrar uma da outra, a condição é chamada de impasse.fonte
O problema dos produtores-consumidores, junto com o problema dos filósofos jantares, é provavelmente o mais simples possível. Ele também possui algum pseudocódigo que o ilustra. Se forem complexos demais para um novato, é melhor tentar entendê-los com mais afinco.
fonte
Vá para o cenário possível simplista em que pode ocorrer um impasse ao apresentar o conceito para seus alunos. Isso envolveria um mínimo de dois threads e um mínimo de dois recursos (eu acho). O objetivo é projetar um cenário em que o primeiro encadeamento tem um bloqueio no recurso um e está esperando que o bloqueio no recurso dois seja liberado, enquanto ao mesmo tempo o encadeamento dois mantém um bloqueio no recurso dois e está esperando por o bloqueio no recurso um a ser liberado.
Não importa realmente quais são os recursos subjacentes; para simplificar, você pode apenas torná-los um par de arquivos nos quais ambos os threads podem gravar.
EDITAR: Isso pressupõe que não haja comunicação entre processos além dos bloqueios mantidos.
fonte
Achei um pouco difícil de entender ao ler o problema dos filósofos de jantar, impasse IMHO está realmente relacionado à alocação de recursos. Gostaria de compartilhar um exemplo mais simples onde 2 Enfermeiros precisam lutar por 3 equipamentos para completar uma tarefa. Embora seja escrito em java. Um método lock () simples é criado para simular como o deadlock acontece, para que possa ser aplicado em outra linguagem de programação também. http://www.justexample.com/wp/example-of-deadlock/
fonte
Exemplo simples de https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Resultado:
Despejo de discussão:
fonte
Aqui está um impasse simples em Java. Precisamos de dois recursos para demonstrar o impasse. No exemplo abaixo, um recurso é o bloqueio de classe (via método de sincronização) e o outro é um inteiro 'i'
fonte
fonte
Aqui está um impasse simples em C #.
Se, um dia, você chamar isso do encadeamento da GUI e outro encadeamento também o chamar - você pode travar. O outro encadeamento chega a EndInvoke, espera que o encadeamento da GUI execute o delegado enquanto mantém o bloqueio. O thread da GUI bloqueia no mesmo bloqueio esperando que o outro thread o libere - o que não acontecerá porque o thread da GUI nunca estará disponível para executar o delegado que o outro thread está esperando. (é claro que o bloqueio aqui não é estritamente necessário - nem o EndInvoke, mas em um cenário um pouco mais complexo, um bloqueio pode ser adquirido pelo chamador por outros motivos, resultando no mesmo impasse.)
fonte
fonte
fonte
fonte
Eu criei um exemplo de DeadLock de trabalho ultra simples: -
No exemplo acima, 2 threads estão executando os métodos sincronizados de dois objetos diferentes. O método sincronizadoA é chamado pelo objeto threadDeadLockA e o método sincronizado B é chamado pelo objeto threadDeadLockB. No métodoA, uma referência de threadDeadLockB é passada e no métodoB uma referência de threadDeadLockA é passada. Agora, cada thread tenta travar o outro objeto. No métodoA, o encadeamento que está bloqueando o threadDeadLockA está tentando obter o bloqueio do objeto threadDeadLockB e, da mesma forma, no métodoB, o segmento que está bloqueando o threadDeadLockB está tentando obter o bloqueio do threadDeadLockA. Assim, ambos os threads aguardarão para sempre criando um deadlock.
fonte
Deixe-me explicar mais claramente usando um exemplo com mais de 2 threads.
Digamos que você tenha n threads, cada um segurando os bloqueios L1, L2, ..., Ln respectivamente. Agora, digamos que, a partir do thread 1, cada thread tenta adquirir o bloqueio de seu thread vizinho. Portanto, o thread 1 é bloqueado para tentar adquirir L2 (como L2 é propriedade do thread 2), o thread 2 é bloqueado para L3 e assim por diante. O thread n é bloqueado para L1. Isso agora é um deadlock, pois nenhum thread é capaz de executar.
No exemplo acima, você pode ver que há três threads segurando
Runnable
task1, task2 e task3. Antes da instrução,sleep(100)
os threads adquirem os três bloqueios dos objetos de trabalho ao entrarem nocall()
método (devido à presença desynchronized
). Mas assim que eles tentamcallAnother()
no objeto do thread vizinho, eles são bloqueados, levando a um deadlock, porque os bloqueios desses objetos já foram tomados.fonte
fonte
Uma maneira sorrateira de entrar em conflito com apenas um único thread é tentar bloquear o mesmo mutex (não recursivo) duas vezes. Este pode não ser o exemplo simples que você estava procurando, mas com certeza eu já encontrei esses casos.
fonte
Aqui está meu exemplo detalhado de impasse , depois de passar muito tempo. Espero que ajude :)
fonte