Escreva o código mais curto para criar um conflito . A execução do código deve parar, para que isso não funcione:
public class DeadlockFail extends Thread{ //Java code
public static void main(String[]a){
Thread t = new DeadlockFail();
t.start();
t.join();
}
//this part is an infinite loop; continues running the loop.
public void run(){while(true){}}
}
Não é necessário ter certeza de que o código entra em conflito , quase com certeza (se você executar por tempo infinito, ele entrará em conflito).
code-golf
concurrency
Justin
fonte
fonte
Code execution must halt
Eu não entendo Como é um impasse se parar? Você quer dizer que estará esperando por algo em vez de apenas girar como um idiota?Respostas:
Dyalog APL (10)
⎕TSYNC
faz com que o encadeamento aguarde até que o encadeamento final termine,⎕TID
fornece o encadeamento atual.O Dyalog APL pode reconhecer os impasses, portanto, responde imediatamente com
O mais divertido é que você nem precisa gerar threads extras, fazendo com que o thread da interface do usuário espere por si só.
Se isso é trapaça e novos encadeamentos são realmente necessários, você pode fazê-lo em 27 caracteres:
F & x
é executadoF
em um novo encadeamento no valorx
e retorna o ID do encadeamento. Então:{⎕TSYNC⎕TID+1}&0
cria um encadeamento que será sincronizado com o encadeamento cujo ID é um maior que o seu,⎕TSYNC&
cria um novo encadeamento que será sincronizado com o encadeamento anterior e obtém um ID um maior que o encadeamento que acabou de ser criado (assumindo que nada mais esteja criando encadeamentos).∇
causa um loop infinito (então continuamos criando threads até que haja um impasse).Isso entrará em conflito assim que o segundo encadeamento for criado antes do início do primeiro, o que é muito breve:
fonte
⎕TSYNC 0'.
⎕TID` é0
.Go, 42
Desculpas, downvoter, por não fornecer como ele funciona. Isso cria um canal anônimo de entradas e lê a partir dele. Isso interrompe o encadeamento principal até que um valor seja enviado pelo canal, o que obviamente nunca acontece, pois nenhum outro encadeamento está ativo e, portanto, um impasse.
fonte
Ruby, 39 caracteres
A idéia de usar uma junção cruzada descaradamente roubada da resposta Java de Johannes Kuhn .
Podemos cortar quatro caracteres (chegando a 35 ) se ajustarmos o código para um ambiente específico. O IRB do console do JRuby é de thread único:
Esta é a minha solução anterior:
é fácil ficar preso em um mutex:
mas esse não é um conflito adequado, porque tecnicamente o segundo thread não está aguardando o primeiro thread. "espera e espera" é uma condição necessária para um impasse, de acordo com a Wikipedia. O primeiro thread não espera e o segundo thread não contém nada.
Rubi,
9795 caractereseste é um impasse clássico. Dois threads competem por dois recursos, tentando novamente se tiverem êxito. Normalmente eles ficam presos dentro de um segundo na minha máquina.
Porém, se ter infinitos encadeamentos (nenhum dos quais consome CPU infinitamente e alguns dos quais impasse) estiver OK,
Rubi,
8785 caracteresDe acordo com o meu teste, ele falha após a contagem de encadeamentos atingir cerca de 4700. Esperemos que não falhe até que cada encadeamento tenha a chance de ser executado (portanto, seja um deadlock ou finalizando e liberando espaço para um novo). De acordo com o meu teste, a contagem de threads não diminui após a falha, o que significa que ocorreu um conflito durante o teste. Além disso, o IRB morreu após o teste.
fonte
o
ep
variáveis? Você não pode simplesmente passarm
en
para o novo segmento?m
en
são globais. Ambos os threads os veem na mesma ordem.o
ep
são thread-local (com escopo definido para a iteração do loop). O usot[...]
provavelmente ficaria caro, e não vejo melhor maneira de passar parâmetros para o thread do que através do fechamento. A adição de parâmetros extras paranew
aumentar o código em dois caracteres.T=Thread;T.new{T.main.join}.join
Python, 46
(auto-impasse)
fonte
from threading import* Semaphore(0).acquire()
é mais curto em um byte, eu achoBash + núcleo GNU, 11 bytes
Cria um FIFO perdido
x
no diretório atual (para que você não precise ter um arquivo com esse nome). Os FIFOs podem ser excluídos da mesma maneira que os arquivos comuns, portanto, não deve ser difícil esclarecer.Um FIFO tem um lado de gravação e um lado de leitura; tentando abrir um bloco até que outro processo abra o outro, e isso parece ter sido intencionalmente projetado como um primitivo de sincronização. Dado que há apenas um segmento aqui, assim que tentamos abri-lo
<x
, ficamos presos. (Você pode cancelar o impasse escrevendo para o FIFO em questão de outro processo.)Esse é um tipo de conflito diferente do quando existem dois recursos, e dois threads têm um e precisam do outro; nesse caso, existem zero recursos e o processo precisa de um. Com base nas outras respostas, acho que isso conta, mas posso entender como um purista de impasse pode querer impedir a resposta.
Pensando bem, eu posso pensar em três situações semelhantes a um impasse:
O impasse "tradicional": dois encadeamentos aguardam a liberação de um bloqueio, que é mantido pelo outro encadeamento.
Um único encadeamento está aguardando a liberação de um bloqueio, mas ele mantém o próprio bloqueio (e, portanto, está impedindo de liberar).
Um único encadeamento está aguardando o lançamento de uma primitiva de sincronização, mas a primitiva de sincronização inicia em um estado naturalmente bloqueado e precisa ser desbloqueada externamente, e nada foi programado para fazer isso.
Esse é um impasse do tipo 3, que é fundamentalmente diferente dos outros dois: você poderia, em teoria, escrever um programa para desbloquear a primitiva de sincronização em questão e executá-la. Dito isso, o mesmo se aplica aos impasses do tipo 1 e 2, já que muitos idiomas permitem liberar um bloqueio que você não possui (você não deveria e não teria motivos para fazê-lo se tivesse um motivo para use os bloqueios em primeiro lugar, mas funciona…). Além disso, vale a pena considerar um programa como
mkfifo x;<x;echo test>x
; esse tipo de programa é o oposto de um deadlock do tipo 2 (ele está tentando abrir as duas extremidades do FIFO, mas não pode abrir uma extremidade até abrir a outra extremidade), mas foi feito a partir dessa via adicionando extra código que nunca é executado após este! Eu acho que o problema é que se um bloqueio é bloqueado ou não depende da intenção por trás do uso do bloqueio, por isso é difícil definir objetivamente (especialmente em um caso como este, onde o único objetivo do bloqueio é produzir um bloqueio intencionalmente )fonte
C #, 100
Veja: O impasse sem bloqueio
fonte
static C
paraMain
?Bash com glibc, 6 bytes
Desculpe reviver um tópico antigo, mas não resisti.
Como raiz:
Do man pldd :
fonte
Java, 191
Ungolfed:
Inicia um novo Thread e
join
nele (aguarde até que esse segmento termine), enquanto o novo Thread faz o mesmo com o Thread original.fonte
Error
vez deException
?Thread.join()
lança umInteruptedException
, que não é uma subclasse deError
.Tcl, 76
Impasse.
Isso cria um novo thread e informa ao outro thread para enviar uma mensagem ao meu thread (script a ser executado).
Mas o envio de uma mensagem para outro Thread geralmente bloqueia até que o script seja executado. E enquanto está bloqueando, nenhuma mensagem é processada; portanto, os dois Threads aguardam o outro processar sua mensagem.
fonte
thread::send
enfileira um script que deve ser executado em outro encadeamento e aguarde a conclusão. Assim, no final temos Tópico 1 de espera para Thread 2, e linha 2 de espera para a linha 1.java alternativo com abuso de monitor (248 charas)
fonte
Scala, 104 bytes
O bloco de inicialização do val preguiçoso suspende até que uma condição seja atendida. Essa condição só pode ser atendida com a leitura do valor de lazy val x - outro encadeamento que deve concluir essa condição não pode fazê-lo. Assim, uma dependência circular é formada e o val preguiçoso não pode ser inicializado.
fonte
Kotlin, 35/37/55 bytes
Tema geral:
Thread.currentThread().join()
.Excluindo bugs da JVM / código muito especializado contra esse envio, esse shoud nunca retorna, pois o encadeamento de execução atual agora está desativado, aguardando sua morte.
Propriedade inválida: 35 bytes (não concorrente): 35 bytes
val a=Thread.currentThread().join()
Colocar isso em qualquer lugar onde uma declaração de propriedade é válida trará um impasse para quem a está inicializando. No caso de uma propriedade de nível superior, esse será o carregador de classes que inicializa a classe da JVM mapeada para esse arquivo (por padrão
[file name]Kt.class
).Não concorrente porque "coloque isso como uma propriedade de nível superior em qualquer lugar" é restritivo.
Função: 37 bytes
fun a()=Thread.currentThread().join()
main (): 55 bytes
fun main(a:Array<String>)=Thread.currentThread().join()
fonte
PowerShell,
362823 bytesAuto-impasse. Recebemos todos os processos
Get-Process
e esperamos pacientemente que cada um deles saia ... o que acontecerá quase nunca, pois o processo estará esperando por si mesmo.Editar - salvou 5 bytes graças a Roman Gräf
fonte
(gps)|%{$_.waitforexit()}
é três bytes mais curto e aguarda a saída de todos os processos.gps
nesse caso, então economizei 5 bytes no total.C (apenas Linux), 31 bytes - Experimente online!
A chamada do sistema 240 (0xf0) é futex (2) ou mutex de espaço de usuário rápido. A documentação afirma que o primeiro argumento é um ponteiro para o futex, o segundo argumento é a operação (0 significa FUTEX_WAIT, ou seja, aguarde até que outro thread desbloqueie o futex). O terceiro argumento é o valor que você espera que o futex tenha enquanto ainda está bloqueado, e o quarto é o ponteiro para o tempo limite (NULL sem tempo limite).
Obviamente, como não há outro segmento para desbloquear o futex, ele esperará para sempre em um impasse auto-infligido. Pode-se verificar (via
top
ou outro gerenciador de tarefas) que o processo não utiliza tempo de CPU, como seria de esperar de um encadeamento em conflito.fonte
Julia 0.6 , 13 bytes
Idioma mais recente que a pergunta. Aguarde uma tarefa (como uma rotina de início), no momento, esteja no mesmo encadeamento; em versões futuras do Julia, pode estar em outro encadeamento) que não esteja agendado para execução.
Experimente online!
fonte
BotEngine, 3x3 = 9 (9 bytes)
A etapa 5 termina com dois bots esperando indefinidamente um pelo outro se mover ... um bot não pode se mover porque está esperando o outro sair do quadrado inferior direito e o outro bot não pode se mover porque está esperando o botão primeiro bot a sair do quadrado central inferior.
fonte
O modelo em cascata (Ratiofall), 13 bytes
Experimente online!
Aqui está uma resposta divertida e inusitada. Esse é o loop infinito mais simples possível no modelo Waterfall (as variáveis no modelo Waterfall diminuem repetidamente sempre que nada mais está acontecendo; esse programa define uma variável que se incrementa sempre que diminui, para que não ocorra nada).
A pergunta pede um impasse, não um loop infinito. No entanto, podemos explorar o comportamento de implementações específicas. No nível de otimização 2 ou superior (o padrão é 3), o intérprete Ratiofall detectará o loop infinito e o otimizará… em um impasse! Portanto, pelo menos se considerarmos as linguagens a serem definidas por sua implementação (que geralmente é o caso neste site), esse programa realmente define um impasse, em vez de um loop infinito.
Você pode ver evidências do impasse no relatório de tempo no Try it Online! link acima:
O programa foi executado por 60 segundos (até que o TIO o encerrasse automaticamente), mas na maior parte do tempo, não havia uso da CPU, tempo gasto pelo programa em execução e tempo gasto pelo kernel em nome do programa.
Para obter evidências ainda mais fortes, você pode executar o Ratiofall em um depurador no nível de chamada do sistema, como
strace
; fazer isso no Linux mostrará o intérprete bloqueado em umafutex
chamada do sistema que tenta bloquear um bloqueio que nunca será liberado.fonte
Perl 6 , 24 bytes
Experimente online!
Crie um semáforo com zero de permissão e tente adquiri-lo.
fonte