Écrivez le code le plus court pour créer un blocage . L'exécution du code doit s'arrêter, donc cela ne fonctionne pas:
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){}}
}
Il n'est pas nécessaire d'être certain que le code se trouve dans une impasse , juste presque sûrement (si vous exécutez pendant un temps infini, il se bloquera).
code-golf
concurrency
Justin
la source
la source
Code execution must halt
Je ne comprends pas. Comment est-ce une impasse s'il s'arrête? Voulez-vous dire qu'il attendra quelque chose plutôt que de simplement tourner comme un trou du cul?Réponses:
Dyalog APL (10)
⎕TSYNC
fait attendre le thread jusqu'à la fin du thread donné,⎕TID
donne le thread actuel.Dyalog APL peut reconnaître les interblocages, il répond donc immédiatement avec
Ce qui est amusant, c'est que vous n'avez même pas besoin de générer de threads supplémentaires, faire attendre le thread d'interface utilisateur lui-même est beaucoup.
Si cela triche et que de nouveaux threads sont réellement nécessaires, vous pouvez le faire en 27 caractères:
F & x
s'exécuteF
dans un nouveau thread sur la valeurx
et renvoie l'ID du thread. Donc:{⎕TSYNC⎕TID+1}&0
crée un thread qui se synchronisera avec le thread dont l'ID est supérieur au sien,⎕TSYNC&
crée un nouveau thread qui se synchronisera avec le thread précédent, et qui obtient un ID supérieur au thread qui vient d'être créé (en supposant que rien d'autre ne crée des threads).∇
provoque une boucle infinie (nous continuons donc à créer des threads jusqu'à ce qu'il y ait un blocage).Cela se bloquera dès que le deuxième thread sera créé avant que le premier ne démarre, ce qui est très bientôt:
la source
⎕TSYNC 0'.
⎕TID` is0
.Allez, 42
Toutes mes excuses, downvoter, pour ne pas avoir fourni comment cela fonctionne. Cela crée un canal anonyme d'entrées et lit à partir de celui-ci. Cela suspend le thread principal jusqu'à ce qu'une valeur soit envoyée sur le canal, ce qui ne se produit évidemment jamais car aucun autre thread n'est actif, et donc un blocage.
la source
Ruby, 39 caractères
L'idée d'utiliser une jointure croisée dérobée sans vergogne à la réponse Java de Johannes Kuhn .
Nous pouvons raser quatre caractères (jusqu'à 35 ) si nous réglons le code sur un environnement spécifique. La console IRB de JRuby est monothread:
Voici ma solution précédente:
obtenir un fil coincé sur un mutex est facile:
mais ce n'est pas une impasse appropriée, car le deuxième thread n'attend techniquement pas le premier thread. "attendre et attendre" est une condition nécessaire pour une impasse selon Wikipedia. Le premier thread n'attend pas et le second thread ne contient rien.
Rubis,
9795 caractèresc'est une impasse classique. Deux threads rivalisent pour deux ressources, réessayant s'ils réussissent. Normalement, ils se coincent en une seconde sur ma machine.
Mais, si avoir un nombre infini de threads (dont aucun ne consomme infiniment CPU et dont certains bloquent) est OK,
Rubis,
8785 caractèresSelon mon test, il échoue après que le nombre de threads atteigne environ 4700. J'espère qu'il n'échouera pas jusqu'à ce que chaque thread ait une chance de s'exécuter (donc soit un blocage, soit une finition et une libération d'espace pour un nouveau). Selon mon test, le nombre de threads ne baisse pas après l'échec, ce qui signifie qu'un blocage s'est produit pendant le test. De plus, l'IRB est décédée après le test.
la source
o
et lesp
variables? Vous ne pouvez pas simplement passerm
etn
pour le nouveau fil?m
etn
sont mondiaux. Les deux threads les voient dans le même ordre.o
etp
sont thread-local (étendues à l'itération de boucle). L'utilisationt[...]
coûterait probablement cher, et je ne vois pas de meilleure façon de transmettre les paramètres au thread que via la fermeture. L'ajout de paramètres supplémentaires pournew
allonger le code de deux caractères.T=Thread;T.new{T.main.join}.join
Python, 46
(autoblocage)
la source
from threading import* Semaphore(0).acquire()
est plus court d'un octet, je penseBash + GNU coreutils, 11 octets
Crée un FIFO errant
x
dans le répertoire courant (vous n'aurez donc pas besoin d'avoir un fichier de ce nom). Les FIFO peuvent être supprimés de la même manière que les fichiers normaux, il ne devrait donc pas être difficile de les effacer.Une FIFO a un côté écriture et un côté lecture; tenter d'ouvrir un bloc jusqu'à ce qu'un autre processus ouvre l'autre, et cela semble avoir été intentionnellement conçu comme une primitive de synchronisation. Étant donné qu'il n'y a qu'un seul fil ici, dès que nous essayons de l'ouvrir
<x
, nous sommes bloqués. (Vous pouvez décoller l'impasse en écrivant sur le FIFO en question à partir d'un autre processus.)Il s'agit d'un type de blocage différent de celui lorsqu'il existe deux ressources et que deux threads en ont chacun un et ont besoin de l'autre; au contraire, dans ce cas, il n'y a aucune ressource et le processus en a besoin. Sur la base des autres réponses, je pense que cela compte, mais je peux comprendre comment un puriste de l'impasse pourrait vouloir refuser la réponse.
À bien y penser, je peux en fait penser à trois situations de type impasse:
Le blocage "traditionnel": deux threads attendent chacun le déblocage, qui est détenu par l'autre thread.
Un seul thread attend la libération d'un verrou, mais il détient le verrou lui-même (et se bloque ainsi de pouvoir le libérer).
Un seul thread attend la libération d'une primitive de synchronisation, mais la primitive de synchronisation démarre dans un état naturellement verrouillé et doit être déverrouillée en externe, et rien n'a été programmé pour le faire.
Il s'agit d'un blocage de type 3, qui est fondamentalement différent des deux autres: vous pourriez, en théorie, écrire un programme pour déverrouiller la primitive de synchronisation en question, puis l'exécuter. Cela dit, la même chose s'applique aux blocages de type 1 et 2, étant donné que de nombreuses langues vous permettent de libérer un verrou que vous ne possédez pas (vous n'êtes pas censé le faire et n'auriez aucune raison de le faire si vous aviez une raison de utiliser les serrures en premier lieu, mais ça marche…). En outre, cela vaut la peine d'envisager un programme comme
mkfifo x;<x;echo test>x
; ce type de programme de l'opposé d'un blocage de type 2 (il essaie d'ouvrir les deux extrémités du FIFO, mais il ne peut ouvrir une extrémité qu'après avoir ouvert l'autre extrémité), mais il a été créé à partir de celui-ci via l'ajout supplémentaire code qui ne s'exécute jamais après celui-ci! Je suppose que le problème est que si un verrou est dans une impasse ou non dépend de l' intention derrière l'utilisation de la serrure, il est donc difficile de définir objectivement (surtout dans un cas comme celui-ci où le seul but de la serrure est de produire intentionnellement une impasse ).la source
C #, 100
Voir: Le blocage sans verrouillage
la source
static C
àMain
?Bash avec glibc, 6 octets
Désolé de faire revivre un vieux fil, mais je n'ai pas pu résister.
En tant que root:
De l' homme pldd :
la source
Java, 191
Non golfé:
Démarre un nouveau thread et
join
sur celui-ci (attendez que ce thread soit terminé), tandis que le nouveau thread fait de même avec le thread d'origine.la source
Error
place deException
?Thread.join()
jette unInteruptedException
, qui n'est pas une sous-classe deError
.Tcl, 76
Impasse.
Cela crée un nouveau Thread et dit à l'autre thread d'envoyer un message à mon thread (script à exécuter).
Mais l'envoi d'un message à un autre thread bloque généralement jusqu'à ce que le script soit exécuté. Et pendant qu'il bloque, aucun message n'est traité, donc les deux threads attendent que l'autre traite leur message.
la source
thread::send
met en file d'attente un script qui doit être exécuté dans un autre thread et attendez qu'il se termine. Donc à la fin, nous avons le fil 1 en attente du fil 2 et le fil 2 en attente du fil 1.java alternatif avec moniteur-abus (248 charas)
la source
Scala, 104 octets
Le bloc d'initialisation paresseux val est suspendu jusqu'à ce qu'une condition soit remplie. Cette condition ne peut être remplie qu'en lisant la valeur de lazy val x - un autre thread qui est censé remplir cette condition ne peut pas le faire. Ainsi, une dépendance circulaire est formée et le val paresseux ne peut pas être initialisé.
la source
Kotlin, 35/37/55 octets
Thème général:
Thread.currentThread().join()
.Excluant les bogues JVM / du code très spécialisé contre cette soumission, ce shoud ne reviendra jamais car le thread d'exécution actuel est maintenant désactivé en attendant de mourir.
Propriété maléfique: 35 octets (non concurrents): 35 octets
val a=Thread.currentThread().join()
Mettre cela n'importe où une déclaration de propriété est valide bloquera celui qui l'initialise. Dans le cas d'une propriété de niveau supérieur, ce sera le chargeur de classe initialisant la classe JVM mappée pour ce fichier (par défaut
[file name]Kt.class
).Pas de concurrence car "mettre cela comme une propriété de niveau supérieur n'importe où" est restrictif.
Fonction: 37 octets
fun a()=Thread.currentThread().join()
main (): 55 octets
fun main(a:Array<String>)=Thread.currentThread().join()
la source
PowerShell,
362823 octetsAutoblocage. Nous obtenons tous les processus avec
Get-Process
, puis attendons patiemment que chacun d'eux se termine ... ce qui n'arrivera presque jamais, car le processus attendra sur lui-même.Edit - Sauvegardé 5 octets grâce à Roman Gräf
la source
(gps)|%{$_.waitforexit()}
est de trois octets plus court et attend que tous les processus se terminent.gps
dans ce cas, donc économisé 5 octets au total.C (Linux uniquement), 31 octets - Essayez-le en ligne!
L'appel système 240 (0xf0) est un futex (2) ou un mutex rapide de l'espace utilisateur. La documentation indique que le premier argument est un pointeur vers le futex, le deuxième argument est l'opération (0 signifie FUTEX_WAIT, c'est-à-dire, attendez qu'un autre thread déverrouille le futex). Le troisième argument est la valeur que vous attendez du futex quand il est encore verrouillé, et le quatrième est le pointeur sur le délai (NULL pour aucun délai).
De toute évidence, puisqu'il n'y a pas d'autre fil pour déverrouiller le futex, il attendra pour toujours dans une impasse auto-infligée. Il peut être vérifié (via
top
ou un autre gestionnaire de tâches) que le processus n'utilise pas de temps CPU, comme nous devrions nous y attendre d'un thread bloqué.la source
Julia 0,6 , 13 octets
Langue plus récente que la question. Attendez une tâche (comme une routine de départ, sera actuellement sur le même thread, dans les futures versions de Julia, elle peut être sur un autre thread) qui n'est pas planifiée pour s'exécuter.
Essayez-le en ligne!
la source
BotEngine, 3x3 = 9 (9 octets)
L'étape 5 se termine avec deux bots attendant indéfiniment de se déplacer ... un bot ne peut pas bouger parce qu'il attend que l'autre se déplace hors du carré en bas à droite, et l'autre bot ne peut pas bouger parce qu'il attend le premier bot à sortir du carré central inférieur.
la source
Le modèle Waterfall (Ratiofall), 13 octets
Essayez-le en ligne!
Voici une réponse amusante et décalée. Il s'agit de la boucle infinie la plus simple possible dans le modèle Waterfall (les variables du modèle Waterfall décrémentent de façon répétée chaque fois que rien d'autre ne se produit; ce programme définit une variable qui s'incrémente chaque fois qu'elle diminue, il n'y a donc aucun moyen que quelque chose puisse se produire).
La question demande un blocage, pas une boucle infinie. Cependant, nous pouvons exploiter le comportement d'implémentations spécifiques. Au niveau d'optimisation 2 ou supérieur (la valeur par défaut est 3), l'interpréteur Ratiofall détectera la boucle infinie et l'optimisera… dans une impasse! Donc au moins si l'on considère les langues comme étant définies par leur implémentation (ce qui est généralement le cas sur ce site), ce programme définit en effet un blocage, plutôt qu'une boucle infinie.
Vous pouvez voir des preuves de l'impasse dans le rapport de temps sur le Try it Online! lien ci-dessus:
Le programme a fonctionné pendant 60 secondes (jusqu'à ce que TIO le termine automatiquement), mais la plupart du temps, il n'y a eu aucune utilisation du processeur, aucun temps passé par le programme en cours d'exécution et aucun temps passé par le noyau pour le compte du programme.
Pour obtenir des preuves encore plus solides, vous pouvez exécuter Ratiofall sous un débogueur de niveau appel système tel que
strace
; faire cela sous Linux montrera l'interpréteur bloquant sur unfutex
appel système qui tente de prendre un verrou qui ne sera jamais libéré.la source
Perl 6 , 24 octets
Essayez-le en ligne!
Créez un sémaphore sans permis, puis essayez de l'acquérir.
la source