Pregunta

Estoy luchando por explicar el "punto muerto" en hilos en palabras fáciles, así que por favor ayuda. ¿Cuál podría ser el mejor ejemplo de "punto muerto" (digamos, en Java), y cómo sucede en los pasos y cómo prevenirlo? Pero sin entrar en detalles demasiado profundos. Sé que es como preguntar dos cosas opuestas, pero aún así. Si tiene alguna experiencia previa en la capacitación de programación concurrente, ¡sería excelente!

¿Fue útil?

Solución

Jack y Jill quieren hacer un sándwich al mismo tiempo. Ambos necesitan una rebanada de pan, por lo que ambos van a obtener la barra de pan y un cuchillo.

Jack obtiene el cuchillo primero, mientras que Jill obtiene la barra de pan primero. Ahora Jack intenta encontrar la barra de pan y Jill intenta encontrar el cuchillo, pero ambos encuentran que lo que necesitan para terminar la tarea ya está en uso. Si ambos deciden esperar hasta que lo que necesitan ya no esté en uso, se esperarán para siempre. Punto muerto.

Otros consejos

La forma más fácil es que dos hilos diferentes para tratar de obtener dos cerraduras en diferentes pedidos:

thread 1:
lock(a)
lock(b)

thread2:
lock(b)
lock(a)

Suponga que el hilo 1 se bloquea A y luego se va a dormir. El hilo 2 obtiene el bloqueo B y luego intenta obtener el bloqueo A; Desde que el bloqueo A se toma, el hilo 2 se pondrá a dormir hasta que el hilo A esté desbloqueado. Ahora el hilo 1 se despierta de nuevo e intenta obtener el bloqueo B y se pondrá a dormir.

Para este caso, hay un par de formas de prevenirlo:

  1. Un hilo nunca debe necesitar contener dos cerraduras simultáneamente.
  2. Si se deben mantener dos cerraduras simultáneamente, siempre deben adquirirse en el mismo orden (por lo que en mi ejemplo anterior, el hilo 2 necesitaría modificarse para solicitar el bloqueo A antes de solicitar el bloqueo B).

Prefiero explicarlo en términos totalmente no relacionados con las computadoras, ya que esa es a menudo la mejor manera de transmitir una idea.

Tengo un hijo de cinco años y una hija de tres años. Ambos quieren hacer el mismo libro de colores.

La hija agarra los lápices mientras el hijo agarra el libro. Tampoco renunciará a lo que tienen hasta que obtengan el otro.

Ese es un punto muerto. No es más simple que eso.

Sus procesos (o niños) están atrapados esperándose y continuarán esperando indefinidamente hasta que entre otro proceso superior (como papá) entra y rompe el punto muerto.

Al menos con los niños, puede (a veces) obtener uno de ellos para ver la razón y renunciar a su cerradura. Esto generalmente no es posible con las computadoras ya que los procesos no están haciendo cualquier cosa Excepto esperar ese recurso (aunque a veces los niños también ingresan a este estado).

La siguiente regla garantizará que el punto muerto no pueda ocurrir:

  • Tener todos Los hilos de ejecución asignan recursos en el mismo orden.

Seguir algunas reglas adicionales hará que sus hilos sean menos propensos a frecuentarse entre sí, pero tenga en cuenta que la regla anterior debería tener prioridad sobre todos los demás:

  • Asignar recursos solo cuando los necesite.
  • Libérelos tan pronto como hayas terminado con ellos.
  Thrd 1 --- Lock A        - atmpt lock on B -   
         \                /                   \
          \              /                     \           
           \            /                       \         
            --- Lock A /                         --- wait for lock on B

  Thrd 2--- Lock B         - atmpt lock on A -   
         \                /                   \
          \              /                     \           
           \            /                       \         
            --- Lock B /                         --- wait for lock on A

El hilo 1 funciona, bloquea A, hace algunas cosas y se interrumpe por el hilo 2 que bloquea B, hace algunas cosas y se interrumpe por el hilo 1 que intenta bloquear B, pero el hilo 2 ha bloqueado B para que el hilo 1 espera y se interrumpe por el hilo 2 que intenta bloquear A, pero el hilo 1 tiene bloqueo en un SO SO SUS 2 tiene que esperar.

Ambos hilos están esperando que el otro hilo libere un bloqueo en un recurso en el que están tratando de obtener un bloqueo ...

Punto muerto

Por lo general, las clases de programación concurrente explican el punto muerto por ejemplos. Creo que el problema del Filósofos gastronómicos Será un buen ejemplo de usar. Puede desarrollar este ejemplo en Java y explicar la ocurrencia del punto muerto cuando dos filósofos sostienen una bifurcación izquierda y están esperando la bifurcación derecha. (o viceversa).

Aprendí muchos conceptos de la programación concurrente utilizando estos ejemplos implementados en Java.

Otra buena manera de demostrar un punto muerto es con SQL Server.

Usando transacciones con diferentes niveles de aislamiento, puede demostrar cómo una transacción esperará indefinidamente una tabla bloqueada por otra transacción.

La ventaja aquí es que puede demostrarlo con SQL Management Studio. He usado esto en el pasado para explicar los plazos a las personas mientras enseñaba los cursos de capacitación de nivel de "Introducción al servidor SQL".

La mayoría de los participantes tienen problemas con la teoría, pero todo (generalmente) se vuelve claro cuando lo ven en acción.

En resumen: la transacción A (que no se ha completado) toma un bloqueo de tabla explícito. Una segunda transacción B intenta leer de la tabla bloqueada por la transacción A. La transacción B está bloqueada hasta que la transacción A se compromete o se retrocede.

Puede explicar esto en el código con bastante facilidad creando dos hilos separados que, a su vez, crean las transacciones. Espero eso ayude.

El punto muerto es cuando dos hilos se esperan, ninguno puede proceder hasta que el otro lo haga primero, y ambos están atascados.

Deadlocking requiere al menos 2 cerraduras, y ambos hilos tienen que contener un código que tome cerraduras y también espera a que se liberen cerraduras.

Thread 1 tiene Lock A y quiere Lock B, por lo que espera a que el Lock B se libere.

Thread 2 tiene Lock B y quiere Lock A, por lo que espera a que el Lock A se libere.

Ahora tienes un punto muerto. Ambos hilos esperan un bloqueo, por lo que tampoco se está ejecutando, por lo que ninguno puede liberar el bloqueo que el otro está esperando.

El punto muerto ocurre cuando tiene 2 recursos diferentes que 2 hilos diferentes deben bloquear para usarlos. Los hilos los bloquean en el orden opuesto, por lo que es imposible que la ejecución continúe hasta que 1 de los hilos retroceda.

Wikipedia tiene un pareja buenos ejemplos de la vida real de punto muerto.

Una cadena de bloqueo ocurre cuando un trabajador es bloqueado por otro trabajador. A no puede continuar debido a B. La cadena puede ser más larga: A está bloqueada por B, B está bloqueada por C, C está bloqueada por D.

Un punto muerto es cuando la cadena de bloqueo forma un bucle. A está bloqueado por B, B por C, C por A y la cadena había formado un bucle, no es posible progreso.

La forma típica de prevenir los puntos muertos es utilizar las arañas de bloqueo: si cada trabajador siempre acuñan los bloqueos en el mismo orden, entonces los puntos muertos no son posibles porque cada bloqueo se produce entre un trabajador que tiene los bloqueos clasificados X y espera recursos clasificados y, donde, donde, donde, donde, donde, donde X> y siempre. Un bucle no puede formarse en este caso, ya que requeriría que al menos un trabajador vaya contra la jerarquía para cerrar el bucle. Así es como va la teoría, al menos. En Prcatice es muy, muy difícil de encontrar jerarquías realistas (y no, la dirección del recurso no funciona).

Si no se pueden evitar los estlocks (p. Ej.

(Ligeramente simplificado) Hay dos personas, atornillando tuercas sobre los pernos.

El procedimiento (mismo para ambos) es:

  1. Recoger una tuerca o un perno
  2. Recoja un perno o una tuerca (lo que no tenga)
  3. Atornilla la tuerca sobre el perno
  4. Coloque el ensamblaje terminado en la pila "terminada".
  5. Si quedan tuercas y pernos, vaya al paso 1

Entonces, ¿qué sucede cuando solo queda una tuerca y un perno? La primera persona toma una tuerca, la segunda toma un perno. Hasta ahora todo bien, pero ahora están atrapados, cada uno con un recurso que los otros necesita.

Sin instrucciones especiales, se sentarán allí estancados para siempre.

O simplemente podrías mostrarles este video

Filósofos gastronómicos: tienes 4 personas sentadas en una mesa y 4 palillos. Necesitas 2 palillos para comer. Imagina que cada filósofo intenta comer de la siguiente manera:

  1. Recoge palillo izquierdo.
  2. Recoge palillo derecho.
  3. Comer.
  4. Coloque el palillo derecho hacia atrás.
  5. Ponga el palillo izquierdo hacia atrás.

Todos hacen el paso 1. Ahora el paso 2 es imposible, ya que cada persona espera a la de su derecha a dejar caer la izquierda, lo que no harán. Este es un punto muerto. Si simplemente se turnaban, todos podrían comer, pero en su lugar todos mueren de hambre.

OK! Creo que lo entiendo ahora.

Tienes razón, el UDID es, por supuesto, no enviado por el navegador. También estaba convencido de que estaba recibido por una falla de seguridad de safari, o algo así, porque TestflightApp agrega una ID única similar a UDID, pero no.

Lo que realmente hacen, es generar un nuevo dispositivo (no relacionado con UDID). Luego, para registrar el dispositivo, generan un perfil específicamente hecho a este dispositivo, que contiene una Carga útil de inscripción que inscribe el dispositivo contra una URL que contiene este dispositivo generado por TestFlightApp.

En este proceso de inscripción, el perfil se le pregunta por el dispositivo, para enviar el UDID (más otros datos). Esta es la información que solicita el perfil:

<array>
    <string>UDID</string>
    <string>IMEI</string>
    <string>ICCID</string>
    <string>VERSION</string>
    <string>PRODUCT</string>
    <string>MODEL</string>
    <string>DEVICE_NAME</string>
</array>

Entonces, cuando el dispositivo pide al servidor TestFlightApp para inscribirse en este dispositivo, pueden relacionar ese dispositivo almacenado en el perfil, con el UDID real del dispositivo actual. Así es como se muestran en el navegador que el proceso se completa y mantiene el UDID.

Pero, esto no completa la respuesta, porque no he resuelto (todavía) cómo realmente relacionen esta sesión web con el UDID, incluso cuando los muertos de la sesión, y el dispositivo de la dispositivo va huérfano. La respuesta parece ser (no confirmada, ¡pero 99% seguro!) Que el proceso de inscripción permite definir una CLIP que se inserte en el menú de su trampolín. Este webclip tiene en la URL escrita el UDID del dispositivo, por lo que en cualquier momento que ingrese en el TestflightApp a través de este webClip, actualiza a la sesión su número UDID, por lo que no importa si la sesión muere.

Espero que mi publicación ayude ahora! Lo siento otra vez para el anterior, incorrecto, anterior.

Imagine you and your girlfriend quarrelled over who should open the door in order to leave the house.The person who apologises will open the door. She is waiting for you to apologise, you are waiting for her to apologise which results in the couple never leaving the house as both refuse to apologise.

Imagine a criminal holding a hostage and asking for a ransom. You show up with a suitcase full of money.

The criminal will never release the hostage before he gets the money. You will never release the money before you get the hostage. Deadlock.


The analogy here are:

  • You and the criminal are the threads
  • The suitcase full of money and the hostage are the resources
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top