Escribe el código más corto para crear un punto muerto . La ejecución del código debe detenerse, por lo que esto no funciona:
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){}}
}
No es necesario estar seguro de que el código entra en un punto muerto , casi con seguridad (si se ejecuta por tiempo infinito, se cerrará).
code-golf
concurrency
Justin
fuente
fuente
Code execution must halt
No entiendo. ¿Cómo es un punto muerto si se detiene? ¿Quieres decir que estará esperando algo en lugar de simplemente girar como un imbécil?Respuestas:
Dyalog APL (10)
⎕TSYNC
hace que el hilo espere hasta que termine el hilo dado,⎕TID
da el hilo actual.Sin embargo, Dyalog APL puede reconocer puntos muertos, por lo que responde inmediatamente con
Lo divertido es que ni siquiera necesita generar hilos adicionales, por lo que el hilo de la interfaz de usuario espera por sí solo es suficiente.
Si esto es trampa y realmente se requieren nuevos hilos, puede hacerlo en 27 caracteres:
F & x
se ejecutaF
en un nuevo hilo en el valorx
y devuelve la ID del hilo. Entonces:{⎕TSYNC⎕TID+1}&0
crea un hilo que se sincronizará con el hilo cuyo ID es uno más alto que el suyo,⎕TSYNC&
crea un nuevo subproceso que se sincronizará con el subproceso anterior, y que obtiene una ID más alta que el subproceso que se acaba de crear (suponiendo que nada más esté creando subprocesos).∇
provoca un bucle infinito (por lo que seguimos creando hilos hasta que hay un punto muerto).Esto se bloqueará tan pronto como se cree el segundo subproceso antes de que comience el primero, que es bastante pronto:
fuente
⎕TSYNC 0'.
⎕TID` es0
.Go, 42
Disculpas, downvoter, por no proporcionar cómo funciona. Esto crea un canal anónimo de entradas y lee de él. Esto detiene el subproceso principal hasta que se envía un valor por el canal, lo que obviamente nunca sucede, ya que no hay otros subprocesos activos y, por lo tanto, punto muerto.
fuente
Ruby, 39 caracteres
La idea de usar una unión cruzada robada descaradamente de la respuesta Java de Johannes Kuhn .
Podemos eliminar cuatro caracteres (llegando a 35 ) si ajustamos el código a un entorno específico. La consola IRB de JRuby es de un solo subproceso:
Esta es mi solución anterior:
conseguir un hilo atascado en un mutex es fácil:
pero este no es un punto muerto adecuado, porque el segundo hilo técnicamente no está esperando el primer hilo. "mantener y esperar" es una condición necesaria para un punto muerto según Wikipedia. El primer hilo no espera, y el segundo hilo no contiene nada.
Rubí,
9795 caracteresEste es un punto muerto clásico. Dos hilos compiten por dos recursos, reintentando si tienen éxito. Normalmente se atascan en un segundo en mi máquina.
Pero, si tiene infinidad de hilos (ninguno de los cuales consume CPU infinitamente y algunos de los cuales están en punto muerto) está bien,
Rubí,
8785 caracteresSegún mi prueba, falla después de que el recuento de subprocesos alcanza aproximadamente 4700. Esperemos que no falle hasta que cada subproceso tenga la oportunidad de ejecutarse (por lo tanto, bloqueo o finalización y liberación de espacio para uno nuevo). Según mi prueba, el recuento de subprocesos no disminuye después de que ocurre la falla, lo que significa que se produjo un punto muerto durante la prueba. Además, IRB murió después de la prueba.
fuente
o
yp
variables? ¿No puedes pasarm
yn
por el nuevo hilo?m
yn
son globales. Ambos hilos los ven en el mismo orden.o
yp
son subprocesos locales (en el ámbito de la iteración del bucle). El usot[...]
probablemente se volvería costoso, y no puedo ver una mejor manera de pasar parámetros al hilo que a través del cierre. Agregar parámetros adicionales paranew
alargar el código en dos caracteres.T=Thread;T.new{T.main.join}.join
Python, 46
(autobloqueo)
fuente
from threading import* Semaphore(0).acquire()
es más corto por un byte, creoBash + GNU coreutils, 11 bytes
Crea una FIFO perdida
x
en el directorio actual (por lo que no deberá tener un archivo con ese nombre). Los FIFO se pueden eliminar de la misma manera que los archivos normales, por lo que no debería ser difícil de eliminar.Un FIFO tiene un lado de escritura y un lado de lectura; intentar abrir un bloque hasta que otro proceso abra el otro, y esto parece haber sido diseñado intencionalmente como una primitiva de sincronización. Dado que solo hay un hilo aquí, tan pronto como intentamos abrirlo
<x
, nos quedamos atascados. (Puede despegar el punto muerto mediante otro proceso escrito al FIFO en cuestión).Este es un tipo de punto muerto diferente del que hay cuando hay dos recursos, y dos hilos tienen uno y necesitan el otro; más bien, en este caso, hay cero recursos y el proceso necesita uno. Basado en las otras respuestas, creo que esto cuenta, pero puedo entender cómo un purista de punto muerto podría querer rechazar la respuesta.
Ahora que lo pienso, en realidad puedo pensar en tres situaciones de punto muerto:
El punto muerto "tradicional": dos subprocesos están esperando que se libere un bloqueo, que está retenido por el otro subproceso.
Un solo subproceso está esperando que se libere un bloqueo, pero retiene el bloqueo en sí (y, por lo tanto, se bloquea para que no se pueda liberar).
Un solo subproceso está esperando que se libere una primitiva de sincronización, pero la primitiva de sincronización comienza en un estado bloqueado naturalmente y tiene que desbloquearse externamente, y no se ha programado nada para hacerlo.
Este es un punto muerto de tipo 3, que es fundamentalmente diferente de los otros dos: en teoría, podría escribir un programa para desbloquear la primitiva de sincronización en cuestión y luego ejecutarlo. Dicho esto, lo mismo se aplica a los puntos muertos de tipo 1 y 2, dado que muchos idiomas le permiten liberar un bloqueo que no es de su propiedad (se supone que no debe hacerlo y no tendría ninguna razón para hacerlo si tuviera una razón para hacerlo). use las cerraduras en primer lugar, pero funciona ...). Además, vale la pena considerar un programa como
mkfifo x;<x;echo test>x
; ese programa es más o menos lo opuesto a un punto muerto de tipo 2 (está tratando de abrir ambos extremos del FIFO, pero no puede abrir un extremo hasta después de abrir el otro extremo), pero se hizo a partir de este agregando más código que nunca se ejecuta después de este! Supongo que el problema es que si un bloqueo está bloqueado o no depende de la intención detrás del uso del bloqueo, por lo que es difícil de definir objetivamente (especialmente en un caso como este donde el único propósito del bloqueo es producir un bloqueo intencionalmente )fuente
C #, 100
Ver: el punto muerto sin bloqueo
fuente
static C
aMain
?Bash con glibc, 6 bytes
Lamento revivir un hilo viejo, pero no pude resistirme.
Como root:
Del hombre pldd :
fuente
Java, 191
Sin golf:
Inicia un nuevo hilo y
join
en él (espere hasta que este hilo haya terminado), mientras que el nuevo hilo hace lo mismo con el hilo original.fuente
Error
lugar deException
?Thread.join()
arroja unInteruptedException
, que no es una subclase deError
.Tcl, 76
Punto muerto.
Esto crea un nuevo hilo y le dice al otro hilo que envíe un mensaje a mi hilo (secuencia de comandos para ejecutar).
Pero enviar un mensaje a otro subproceso generalmente bloquea hasta que se haya ejecutado el script. Y mientras se está bloqueando, no se procesan mensajes, por lo que ambos subprocesos esperan que el otro procese su mensaje.
fuente
thread::send
pone en cola un script que debe ejecutarse en otro subproceso y espera a que se complete. Así que al final tenemos el Hilo 1 esperando el Hilo 2, y el Hilo 2 esperando el Hilo 1.Java alternativo con abuso de monitor (248 charas)
fuente
Scala, 104 bytes
El bloque de inicialización val perezoso se suspende hasta que se cumpla una condición. Esta condición solo puede cumplirse leyendo el valor de lazy val x: otro hilo que se supone que completa esta condición no puede hacerlo. Por lo tanto, se forma una dependencia circular y el vago val no se puede inicializar.
fuente
Kotlin, 35/37/55 bytes
Tema general:
Thread.currentThread().join()
.Excluyendo errores de JVM / código muy especializado en contra de esta presentación, esto nunca debería volver ya que el hilo de ejecución actual ahora está deshabilitado esperando que muera.
Propiedad malvada: 35 bytes (no competitiva): 35 bytes
val a=Thread.currentThread().join()
Poner esto en cualquier lugar donde una declaración de propiedad sea válida bloqueará a quien la esté inicializando. En el caso de una propiedad de nivel superior, ese será el cargador de clases que inicializa la clase JVM asignada para ese archivo (de forma predeterminada
[file name]Kt.class
).No competir porque "poner esto como una propiedad de nivel superior en cualquier lugar" es restrictivo.
Función: 37 bytes
fun a()=Thread.currentThread().join()
main (): 55 bytes
fun main(a:Array<String>)=Thread.currentThread().join()
fuente
PowerShell,
362823 bytesAuto-punto muerto. Recibimos todos los procesos
Get-Process
y luego esperamos pacientemente a que cada uno de ellos salga ... lo que sucederá aproximadamente nunca, ya que el proceso se esperará solo.Editar - Guardado 5 bytes gracias a Roman Gräf
fuente
(gps)|%{$_.waitforexit()}
es tres bytes más corto y espera a que todos los procesos salgan.gps
en ese caso, por lo que ahorró 5 bytes en total.C (solo Linux), 31 Bytes - ¡ Pruébelo en línea!
La llamada al sistema 240 (0xf0) es futex (2) , o mutex de espacio de usuario rápido. La documentación indica que el primer argumento es un puntero al futex, el segundo argumento es la operación (0 significa FUTEX_WAIT, es decir, espere hasta que otro hilo desbloquee el futex). El tercer argumento es el valor que espera que tenga el futex mientras está bloqueado, y el cuarto es el puntero al tiempo de espera (NULL sin tiempo de espera).
Obviamente, dado que no hay otro hilo para desbloquear el futex, esperará para siempre en un punto muerto autoinfligido. Se puede verificar (a través de
top
u otro administrador de tareas) que el proceso no utiliza tiempo de CPU, como deberíamos esperar de un subproceso bloqueado.fuente
Julia 0.6 , 13 bytes
Idioma más nuevo que la pregunta. Espere una tarea (como una rutina de inicio, actualmente estará en el mismo hilo, en futuras versiones de Julia puede estar en otro hilo) que no está programada para ejecutarse.
Pruébalo en línea!
fuente
BotEngine, 3x3 = 9 (9 bytes)
El paso 5 termina con dos bots que esperan indefinidamente que el otro se mueva ... uno no puede moverse porque está esperando que el otro salga del cuadro inferior derecho, y el otro bot no puede moverse porque está esperando primer bot que se mueve fuera del cuadrado central inferior.
fuente
El modelo de cascada (Ratiofall), 13 bytes
Pruébalo en línea!
Aquí hay una divertida respuesta extravagante. Este es el bucle infinito más simple posible en The Waterfall Model (las variables en The Waterfall Model disminuyen repetidamente cada vez que no sucede nada más; este programa define una variable que se incrementa cada vez que disminuye, por lo que no hay forma de que algo pueda suceder).
La pregunta pide un punto muerto, no un bucle infinito. Sin embargo, podemos explotar el comportamiento de implementaciones específicas. En el nivel de optimización 2 o superior (el valor predeterminado es 3), el intérprete Ratiofall detectará el bucle infinito y lo optimizará ... ¡hasta un punto muerto! Entonces, al menos si consideramos que los idiomas se definen por su implementación (que suele ser el caso en este sitio), este programa define un punto muerto, en lugar de un bucle infinito.
¡Puede ver evidencia del punto muerto en el informe de tiempo en Try it Online! enlace de arriba:
El programa se ejecutó durante 60 segundos (hasta que TIO lo finalizó automáticamente), pero durante la mayor parte de ese tiempo, no hubo uso de CPU, no pasó tiempo ejecutando el programa y el kernel no dedicó tiempo en nombre del programa.
Para obtener evidencia aún más sólida, puede ejecutar Ratiofall bajo un depurador de nivel de llamada del sistema como
strace
; Al hacer esto en Linux, se mostrará el bloqueo del intérprete en unafutex
llamada al sistema que intenta tomar un bloqueo que nunca se liberará.fuente
Perl 6 , 24 bytes
Pruébalo en línea!
Cree un semáforo con cero permisos y luego intente adquirirlo.
fuente