Me gustaría explicar los puntos muertos de subprocesos a los novatos. He visto muchos ejemplos de interbloqueos en el pasado, algunos usando código y otros usando ilustraciones (como los famosos 4 autos ). También hay problemas clásicos que se bloquean fácilmente, como The Dining Philosophers , pero pueden ser demasiado complejos para que un principiante real los comprenda por completo.
Estoy buscando el ejemplo de código más simple para ilustrar qué son los interbloqueos. El ejemplo debería:
- Relacionarse con un escenario de programación "real" que tenga algún sentido
- Sea muy breve, sencillo y directo
¿Que recomiendas?
multithreading
language-agnostic
deadlock
Roee Adler
fuente
fuente
Respuestas:
Quizás una simple situación bancaria.
Obviamente, si hay dos subprocesos que intentan ejecutar la transferencia ( a, b ) y la transferencia ( b, a ) al mismo tiempo, se producirá un punto muerto porque intentarán adquirir los recursos en orden inverso.
Este código también es ideal para buscar soluciones al punto muerto. ¡Espero que esto ayude!
fuente
sync
puede ser algo como:sync(Account & a) { a.mutex.lock(); }
.Deja que la naturaleza explique el estancamiento
Punto muerto: rana contra serpiente
fuente
Aquí hay un ejemplo de código del departamento de ciencias de la computación de una universidad en Taiwán que muestra un ejemplo simple de Java con bloqueo de recursos. Eso es muy relevante para mí en la "vida real". Código a continuación:
fuente
Si el método1 () y el método2 () serán llamados por dos o muchos subprocesos, hay una buena posibilidad de un punto muerto porque si el subproceso 1 adquiere el bloqueo en el objeto String mientras se ejecuta el método1 () y el subproceso 2 adquiere el bloqueo en el objeto Integer mientras se ejecuta el método2 () ambos estarán esperando que el otro libere el bloqueo en Integer y String para continuar, lo que nunca sucederá.
fuente
Uno de los ejemplos simples de interbloqueo con los que me he encontrado.
fuente
private int index
ahí?Aquí hay un ejemplo simple en C ++ 11.
fuente
Por favor vea mi respuesta a esta pregunta . En pocas palabras, siempre que dos subprocesos necesiten adquirir dos recursos diferentes, y hacerlo en diferentes órdenes, puede obtener puntos muertos.
fuente
Un ejemplo en el que puedo pensar es el escenario Mesa, linterna y baterías. Imagina una linterna y un par de pilas colocadas encima de una mesa. Si tuvieras que caminar hasta esta mesa y agarrar las baterías mientras otra persona tiene la linterna, ambos se verán obligados a mirarse torpemente el uno al otro mientras esperan quién colocará primero su artículo en la mesa. Este es un ejemplo de punto muerto. Usted y la persona están esperando recursos, pero ninguno de ustedes está renunciando a su recurso.
De manera similar, en un programa, el interbloqueo ocurre cuando dos o más subprocesos (usted y la otra persona) están esperando que se liberen dos o más candados (linterna y baterías) y las circunstancias en el programa son tales que los candados nunca se liberan ( ambos tienen una pieza del rompecabezas).
Si conoce Java, así es como puede representar este problema:
Si ejecuta este ejemplo, notará que a veces las cosas funcionan bien y correctamente. Pero a veces su programa simplemente no imprime nada. Esto se debe a que una persona tiene las baterías mientras que otra persona tiene la linterna, lo que les impide encender la linterna y provocar un bloqueo.
Este ejemplo es similar al ejemplo dado por los tutoriales de Java: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Otro ejemplo es el ejemplo de bucle:
Este ejemplo puede imprimir 'No hecho' una y otra vez o nunca puede imprimir 'No hecho' en absoluto. Lo primero ocurre porque el primer hilo adquiere el bloqueo de clase y nunca lo libera, lo que impide que el segundo hilo acceda a 'stopLoop'. Y lo último sucede porque el segundo hilo comenzó antes que el primer hilo, lo que hace que la variable 'done' sea verdadera antes de que se ejecute el primer hilo.
fuente
fuente
Sin embargo, considero que el problema de Dining Philosophers es uno de los ejemplos más simples de mostrar interbloqueos, ya que los 4 requisitos de interbloqueo se pueden ilustrar fácilmente con el dibujo (especialmente la espera circular).
Considero que los ejemplos del mundo real son mucho más confusos para el novato, aunque no puedo pensar en un buen escenario del mundo real en la parte superior de mi cabeza en este momento (soy relativamente inexperto con la concurrencia del mundo real).
fuente
Recientemente me di cuenta de que las peleas entre parejas no son más que un punto muerto ... donde normalmente uno de los procesos tiene que fallar para resolverlo, por supuesto que es el de menor prioridad (Chico;)).
Aquí está la analogía ...
Proceso1: Niña (G) Proceso2: Niño (B) Recurso1
: Lo siento Recurso2 : Aceptar el propio error
Condiciones necesarias:
1. Exclusión mutua: Solo uno de los G o B puede pedir perdón o aceptar su propio Error a la vez.
2. Espera y espera: En un momento, uno está sosteniendo Lo siento y otro Aceptando su propio error, uno está esperando Aceptar su propio error para liberar el perdón, y otro está esperando a que el perdón lo libere aceptando su propio error.
3. Sin prerrogativa: Ni siquiera Dios puede obligar a B o G a liberar su propio error. ¿Y voluntariamente? ¿¿Me estás tomando el pelo??
4. Espera circular: Una vez más, el que se arrepiente espera que el otro acepte sus propios errores, y el que acepta sus propios errores quiere que el otro primero pida perdón. Entonces es circular.
Entonces, los puntos muertos ocurren cuando todas estas condiciones están vigentes al mismo tiempo, y ese es siempre el caso en una pelea de pareja;)
Fuente: http://www.quora.com/Saurabh-Pandey-3/Posts/Never-ending-couple-fights-a-deadlock
fuente
Otro ejemplo simple de interbloqueo con dos recursos diferentes y dos subprocesos esperando que el otro libere el recurso. Directamente de examples.oreilly.com/jenut/Deadlock.java
fuente
If all goes as planned, deadlock will occur, and the program will never exit.
¿Podemos hacer que este ejemplo sea unguarantee
punto muerto?El punto muerto puede ocurrir en una situación en la que un
Girl1
quiere coquetear con alguienGuy2
que es atrapado por otroGirl2
yGirl2
quiere coquetear con unGuy1
que está atrapadoGirl1
. Dado que ambas chicas están esperando deshacerse de la otra, la condición se llama punto muerto.fuente
El problema de los productores-consumidores junto con el problema de los filósofos de la comida es probablemente tan simple como parece. También tiene un pseudocódigo que lo ilustra. Si son demasiado complejos para un novato, será mejor que se esfuercen más por comprenderlos.
fuente
Opte por el escenario posible simplista en el que puede ocurrir un punto muerto al presentar el concepto a sus estudiantes. Esto implicaría un mínimo de dos subprocesos y un mínimo de dos recursos (creo). El objetivo es diseñar un escenario en el que el primer hilo tenga un bloqueo en el recurso uno y esté esperando que se libere el bloqueo del recurso dos, mientras que al mismo tiempo el hilo dos mantiene un bloqueo en el recurso dos y está esperando el bloqueo del recurso uno se liberará.
Realmente no importa cuáles sean los recursos subyacentes; en aras de la simplicidad, podría convertirlos en un par de archivos en los que ambos subprocesos puedan escribir.
EDITAR: Esto asume que no hay comunicación entre procesos que no sean los bloqueos retenidos.
fuente
Encontré que un poco difícil de entender al leer el problema de los filósofos de la cena, el punto muerto en mi humilde opinión está realmente relacionado con la asignación de recursos. Me gustaría compartir un ejemplo más simple en el que 2 enfermeras deben luchar por 3 equipos para completar una tarea. Aunque está escrito en java. Se crea un método lock () simple para simular cómo ocurre el interbloqueo, por lo que también se puede aplicar en otro lenguaje de programación. http://www.justexample.com/wp/example-of-deadlock/
fuente
Ejemplo simple de https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Salida:
Volcado de hilo:
fuente
Aquí hay un simple punto muerto en Java. Necesitamos dos recursos para demostrar el estancamiento. En el siguiente ejemplo, un recurso es el bloqueo de clase (a través del método de sincronización) y el otro es un entero 'i'
fuente
fuente
Aquí hay un simple interbloqueo en C #.
Si, un día, llama a esto desde el hilo de la GUI y otro hilo también lo llama, es posible que se bloquee. El otro subproceso llega a EndInvoke, espera a que el subproceso de la GUI ejecute el delegado mientras mantiene el bloqueo. El subproceso de la GUI se bloquea en el mismo bloqueo esperando a que el otro subproceso lo libere, lo que no ocurrirá porque el subproceso de la GUI nunca estará disponible para ejecutar el delegado que el otro subproceso está esperando. (Por supuesto, el bloqueo aquí no es estrictamente necesario, ni quizás EndInvoke, pero en un escenario un poco más complejo, la persona que llama podría adquirir un bloqueo por otras razones, lo que da como resultado el mismo interbloqueo).
fuente
fuente
fuente
fuente
He creado un ejemplo de DeadLock de trabajo ultra simple: -
En el ejemplo anterior, 2 subprocesos están ejecutando los métodos sincronizados de dos objetos diferentes. El objeto threadDeadLockA llama al método sincronizado A y el objeto threadDeadLockB llama al método B sincronizado. En el métodoA se pasa una referencia de threadDeadLockB y en el métodoB se pasa una referencia de threadDeadLockA. Ahora, cada hilo intenta bloquear el otro objeto. En el métodoA, el hilo que tiene un bloqueo en threadDeadLockA está tratando de bloquear el objeto threadDeadLockB y, de manera similar, en el métodoB el hilo que tiene un bloqueo en threadDeadLockB está tratando de bloquear el threadDeadLockA. Por lo tanto, ambos hilos esperarán para siempre creando un punto muerto.
fuente
Permítanme explicar más claramente usando un ejemplo que tiene más de 2 hilos.
Supongamos que tiene n subprocesos, cada uno de los cuales mantiene bloqueos L1, L2, ..., Ln respectivamente. Ahora digamos, a partir del hilo 1, cada hilo intenta adquirir el bloqueo de su hilo vecino. Por lo tanto, el hilo 1 se bloquea para intentar adquirir L2 (ya que L2 es propiedad del hilo 2), el hilo 2 se bloquea para L3 y así sucesivamente. El hilo n se bloquea para L1. Esto ahora es un punto muerto ya que ningún subproceso puede ejecutarse.
En el ejemplo anterior, puede ver que hay tres subprocesos que contienen
Runnable
s task1, task2 y task3. Antes del enunciado,sleep(100)
los hilos adquieren los bloqueos de los tres objetos de trabajo cuando ingresan alcall()
método (debido a la presencia desynchronized
). Pero tan pronto como intentan encallAnother()
el objeto de su hilo vecino, se bloquean, lo que lleva a un punto muerto, porque los bloqueos de esos objetos ya se han tomado.fuente
fuente
Una forma furtiva de interbloqueo con un solo hilo es intentar bloquear el mismo mutex (no recursivo) dos veces. Puede que este no sea el ejemplo simple que estaba buscando, pero, efectivamente, ya encontré tales casos.
fuente
Aquí está mi ejemplo detallado de interbloqueo , después de pasar mucho tiempo. Espero eso ayude :)
fuente