tutorial threading thread lock ejemplos and multithreading language-agnostic deadlock

multithreading - threading - Ejemplos de punto muerto simple



python threading (27)

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 "real" relevante para mí. Código a continuación:

/** * Adapted from The Java Tutorial * Second Edition by Campione, M. and * Walrath, K.Addison-Wesley 1998 */ /** * This is a demonstration of how NOT to write multi-threaded programs. * It is a program that purposely causes deadlock between two threads that * are both trying to acquire locks for the same two resources. * To avoid this sort of deadlock when locking multiple resources, all threads * should always acquire their locks in the same order. **/ public class Deadlock { public static void main(String[] args){ //These are the two resource objects //we''ll try to get locks for final Object resource1 = "resource1"; final Object resource2 = "resource2"; //Here''s the first thread. //It tries to lock resource1 then resource2 Thread t1 = new Thread() { public void run() { //Lock resource 1 synchronized(resource1){ System.out.println("Thread 1: locked resource 1"); //Pause for a bit, simulating some file I/O or //something. Basically, we just want to give the //other thread a chance to run. Threads and deadlock //are asynchronous things, but we''re trying to force //deadlock to happen here... try{ Thread.sleep(50); } catch (InterruptedException e) {} //Now wait ''till we can get a lock on resource 2 synchronized(resource2){ System.out.println("Thread 1: locked resource 2"); } } } }; //Here''s the second thread. //It tries to lock resource2 then resource1 Thread t2 = new Thread(){ public void run(){ //This thread locks resource 2 right away synchronized(resource2){ System.out.println("Thread 2: locked resource 2"); //Then it pauses, for the same reason as the first //thread does try{ Thread.sleep(50); } catch (InterruptedException e){} //Then it tries to lock resource1. //But wait! Thread 1 locked resource1, and //won''t release it till it gets a lock on resource2. //This thread holds the lock on resource2, and won''t //release it till it gets resource1. //We''re at an impasse. Neither thread can run, //and the program freezes up. synchronized(resource1){ System.out.println("Thread 2: locked resource 1"); } } } }; //Start the two threads. //If all goes as planned, deadlock will occur, //and the program will never exit. t1.start(); t2.start(); } }

Me gustaría explicar cómo entablar interbloqueos para los novatos. He visto muchos ejemplos de callejones sin salida en el pasado, algunos usan códigos y otros usan ilustraciones (como los famosos 4 autos ). También hay problemas clásicos fácilmente estancados como The Dining Philosophers , pero estos pueden ser demasiado complejos para que un novato real los capte por completo.

Estoy buscando el ejemplo de código más simple para ilustrar qué son los puntos muertos. El ejemplo debería:

  1. Relacionarse con un escenario de programación "real" que tenga algún sentido
  2. Se muy corto, simple y directo

¿Que recomiendas?


Aquí hay un punto muerto simple en Java. Necesitamos dos recursos para demostrar un punto muerto. 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 número entero ''i''

public class DeadLock { static int i; static int k; public static synchronized void m1(){ System.out.println(Thread.currentThread().getName()+" executing m1. Value of i="+i); if(k>0){i++;} while(i==0){ System.out.println(Thread.currentThread().getName()+" waiting in m1 for i to be > 0. Value of i="+i); try { Thread.sleep(10000);} catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { Thread t1 = new Thread("t1") { public void run() { m1(); } }; Thread t2 = new Thread("t2") { public void run() { try { Thread.sleep(100);} catch (InterruptedException e) { e.printStackTrace(); } k++; m1(); } }; t1.start(); t2.start(); } }


Aquí hay un punto muerto simple en c #

void UpdateLabel(string text) { lock(this) { if(MyLabel.InvokeNeeded) { IAsyncResult res = MyLable.BeginInvoke(delegate() { MyLable.Text = text; }); MyLabel.EndInvoke(res); } else { MyLable.Text = text; } } }

Si, un día, usted llama esto desde el hilo de la interfaz gráfica de usuario, y otro hilo lo llama también, podría estancarse. El otro subproceso llega a EndInvoke, espera a que el subproceso de GUI ejecute al delegado mientras mantiene el bloqueo. Los bloques de subprocesos de GUI en el mismo bloqueo esperan que el otro subproceso los libere, lo que no ocurre 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 tampoco es el EndInvoke, pero en un escenario un poco más complejo, la persona que llama puede adquirir un bloqueo por otras razones, lo que da como resultado el mismo punto muerto).


Busque el escenario simplista posible en el que puede producirse un punto muerto al presentar el concepto a sus alumnos. Esto implicaría un mínimo de dos hilos 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 segundo hilo mantiene un bloqueo en el recurso dos, y está esperando el bloqueo en el recurso uno para ser lanzado.

Realmente no importa cuáles son los recursos subyacentes; por razones de simplicidad, podría hacer que sean un par de archivos en los que ambos hilos puedan escribir.

EDITAR: Esto supone que no hay comunicación entre procesos aparte de los bloqueos retenidos.


Considero que el problema de los Filósofos del comedor es uno de los ejemplos más sencillos de mostrar bloqueos, ya que los 4 requisitos de interbloqueo se pueden ilustrar fácilmente mediante el dibujo (especialmente la espera circular).

Considero que los ejemplos del mundo real son mucho más confusos para el novato, aunque ahora mismo no puedo pensar en un buen escenario real en el mundo real (soy relativamente inexperto con la concurrencia en el mundo real).


Deja que la naturaleza explique el punto muerto,

Punto muerto: rana contra serpiente

"Me encantaría haberlos visto por caminos separados, pero estaba exhausto", dijo el fotógrafo. "La rana estaba tratando de sacar a la serpiente todo el tiempo , pero la serpiente simplemente no la soltaba" .


Descubrí que es un poco difícil de entender al leer el problema de los filósofos del comedor, el interbloqueo en mi humilde opinión en realidad está relacionado con la asignación de recursos. Me gustaría compartir un ejemplo más simple donde 2 enfermeras necesitan luchar por 3 equipos para completar una tarea. Aunque está escrito en Java. Se crea un método simple lock () para simular cómo se produce el punto muerto, por lo que también se puede aplicar en otro lenguaje de programación. http://www.justexample.com/wp/example-of-deadlock/


Ejemplo simple de https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

public class Deadlock { public static void printMessage(String message) { System.out.println(String.format("%s %s ", Thread.currentThread().getName(), message)); } private static class Friend { private String name; public Friend(String name) { this.name = name; } public void bow(Friend friend) { printMessage("Acquiring lock on " + this.name); synchronized(this) { printMessage("Acquired lock on " + this.name); printMessage(name + " bows " + friend.name); friend.bowBack(this); } } public void bowBack(Friend friend) { printMessage("Acquiring lock on " + this.name); synchronized (this) { printMessage("Acquired lock on " + this.name); printMessage(friend.name + " bows back"); } } } public static void main(String[] args) throws InterruptedException { Friend one = new Friend("one"); Friend two = new Friend("two"); new Thread(new Runnable() { @Override public void run() { one.bow(two); } }).start(); new Thread(new Runnable() { @Override public void run() { two.bow(one); } }).start(); } }

Salida:

Thread-0 Acquiring lock on one Thread-1 Acquiring lock on two Thread-0 Acquired lock on one Thread-1 Acquired lock on two Thread-1 two bows one Thread-0 one bows two Thread-1 Acquiring lock on one Thread-0 Acquiring lock on two

Thread Dump:

2016-03-14 12:20:09 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.74-b02 mixed mode): "DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00007f472400a000 nid=0x3783 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Thread-1" #12 prio=5 os_prio=0 tid=0x00007f472420d800 nid=0x37a3 waiting for monitor entry [0x00007f46e89a5000] java.lang.Thread.State: BLOCKED (on object monitor) at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102) - waiting to lock <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92) - locked <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$2.run(ThreadJoin.java:141) at java.lang.Thread.run(Thread.java:745) "Thread-0" #11 prio=5 os_prio=0 tid=0x00007f472420b800 nid=0x37a2 waiting for monitor entry [0x00007f46e8aa6000] java.lang.Thread.State: BLOCKED (on object monitor) at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102) - waiting to lock <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92) - locked <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$1.run(ThreadJoin.java:134) at java.lang.Thread.run(Thread.java:745) "Monitor Ctrl-Break" #10 daemon prio=5 os_prio=0 tid=0x00007f4724211000 nid=0x37a1 runnable [0x00007f46e8def000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:170) at java.net.SocketInputStream.read(SocketInputStream.java:141) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) - locked <0x000000076d20afb8> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.fill(BufferedReader.java:161) at java.io.BufferedReader.readLine(BufferedReader.java:324) - locked <0x000000076d20afb8> (a java.io.InputStreamReader) at java.io.BufferedReader.readLine(BufferedReader.java:389) at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:93) at java.lang.Thread.run(Thread.java:745) "Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f47240c9800 nid=0x3794 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f47240c6800 nid=0x3793 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f47240c4000 nid=0x3792 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f47240c2800 nid=0x3791 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f47240bf800 nid=0x3790 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f47240be000 nid=0x378f waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f472408c000 nid=0x378e in Object.wait() [0x00007f46e98c5000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076cf88ee0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x000000076cf88ee0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209) "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f4724087800 nid=0x378d in Object.wait() [0x00007f46e99c6000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076cf86b50> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x000000076cf86b50> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "VM Thread" os_prio=0 tid=0x00007f4724080000 nid=0x378c runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f472401f000 nid=0x3784 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f4724021000 nid=0x3785 runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f4724022800 nid=0x3786 runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f4724024800 nid=0x3787 runnable "GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f4724026000 nid=0x3788 runnable "GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f4724028000 nid=0x3789 runnable "GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f4724029800 nid=0x378a runnable "GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f472402b800 nid=0x378b runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f47240cc800 nid=0x3795 waiting on condition JNI global references: 16 Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x00007f46dc003f08 (object 0x000000076d0583a0, a com.anantha.algorithms.ThreadJoin$Friend), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x00007f46dc006008 (object 0x000000076d0583e0, a com.anantha.algorithms.ThreadJoin$Friend), which is held by "Thread-1" Java stack information for the threads listed above: =================================================== "Thread-1": at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102) - waiting to lock <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92) - locked <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$2.run(ThreadJoin.java:141) at java.lang.Thread.run(Thread.java:745) "Thread-0": at com.anantha.algorithms.ThreadJoin$Friend.bowBack(ThreadJoin.java:102) - waiting to lock <0x000000076d0583e0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$Friend.bow(ThreadJoin.java:92) - locked <0x000000076d0583a0> (a com.anantha.algorithms.ThreadJoin$Friend) at com.anantha.algorithms.ThreadJoin$1.run(ThreadJoin.java:134) at java.lang.Thread.run(Thread.java:745) Found 1 deadlock. Heap PSYoungGen total 74752K, used 9032K [0x000000076cf80000, 0x0000000772280000, 0x00000007c0000000) eden space 64512K, 14% used [0x000000076cf80000,0x000000076d8520e8,0x0000000770e80000) from space 10240K, 0% used [0x0000000771880000,0x0000000771880000,0x0000000772280000) to space 10240K, 0% used [0x0000000770e80000,0x0000000770e80000,0x0000000771880000) ParOldGen total 171008K, used 0K [0x00000006c6e00000, 0x00000006d1500000, 0x000000076cf80000) object space 171008K, 0% used [0x00000006c6e00000,0x00000006c6e00000,0x00000006d1500000) Metaspace used 3183K, capacity 4500K, committed 4864K, reserved 1056768K class space used 352K, capacity 388K, committed 512K, reserved 1048576K


El problema productores-consumidores junto con el problema de los filósofos del comedor es probablemente tan simple como se va a poner. También tiene un pseudocódigo que lo ilustra. Si son demasiado complejos para un novato, será mejor que intenten comprenderlos mejor.


El punto muerto puede ocurrir en una situación en la que una Girl1 quiere coquetear con Guy2 , que es atrapada por otra Girl2 , y Girl2 quiere coquetear con una Guy1 que es atrapada por Girl1 . Dado que ambas chicas están esperando deshacerse, la condición se llama punto muerto.

class OuchTheGirls { public static void main(String[] args) { final String resource1 = "Guy1"; final String resource2 = "Guy2"; // Girl1 tries to lock resource1 then resource2 Thread Girl1 = new Thread(() -> { synchronized (resource1) { System.out.println("Thread 1: locked Guy1"); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource2) { System.out.println("Thread 1: locked Guy2"); } } }); // Girl2 tries to lock Guy2 then Guy1 Thread Girl2 = new Thread(() -> { synchronized (resource2) { System.out.println("Thread 2: locked Guy2"); try { Thread.sleep(100);} catch (Exception e) {} synchronized (resource1) { System.out.println("Thread 2: locked Guy1"); } } }); Girl1.start(); Girl2.start(); } }


Por favor vea mi respuesta a esta pregunta . En pocas palabras cada vez que dos hilos necesitan adquirir dos recursos diferentes, y hacerlo en diferentes órdenes, entonces puede obtener puntos muertos.


Recientemente me di cuenta de que las peleas entre parejas no son más que un punto muerto ... donde generalmente uno de los procesos tiene que colapsar para resolverlo, por supuesto es de menor prioridad (Chico;)).

Aquí está la analogía ...

Proceso1: Chica (G) Proceso2: Niño (B)
Resource1: Sorry Resource2: Aceptar el propio error

Condiciones necesarias:
1. Exclusión mutua: solo uno de G o B puede pedir perdón o aceptar su propio error a la vez.
2. Espera y espera: A la vez, uno está sosteniendo Lo siento y otros Aceptando el propio error, uno está esperando Aceptar el propio error para liberarlo, y el otro está esperando que lo suelte para aceptar su propio error.
3. Sin previo aviso: ni siquiera Dios puede forzar a B o G a liberar Lo sentimos o Aceptar su propio error. ¿Y voluntariamente? ¿¿Me estás tomando el pelo??
4. Espera circular: una vez más, el que tiene pena espera a que otros acepten sus propios errores, y una persona que acepta los propios errores quiere que otros le digan perdón primero. Entonces es circular.

Así que se producen bloqueos cuando todas estas condiciones están en vigencia al mismo tiempo, y ese es siempre el caso en un par de peleas;)

Fuente: http://www.quora.com/Saurabh-Pandey-3/Posts/Never-ending-couple-fights-a-deadlock


Sé que esta pregunta ya ha sido respondida, pero aquí hay otro ejemplo simple: esta vez usando C ++ 11

#include <mutex> // mutex #include <iostream> // cout #include <cstdio> // getchar #include <thread> // this_thread, yield #include <future> // async #include <chrono> // seconds using namespace std; mutex _m1; mutex _m2; // Deadlock will occur because func12 and func21 acquires the two locks in reverse order void func12() { unique_lock<mutex> l1(_m1); this_thread::yield(); // hint to reschedule this_thread::sleep_for( chrono::seconds(1) ); unique_lock<mutex> l2(_m2 ); } void func21() { unique_lock<mutex> l2(_m2); this_thread::yield(); // hint to reschedule this_thread::sleep_for( chrono::seconds(1) ); unique_lock<mutex> l1(_m1); } int main( int argc, char* argv[] ) { async(func12); func21(); cout << "All done!"; // this won''t be executed because of deadlock getchar(); }


Si method1 () y method2 () ambos serán llamados por dos o muchos hilos, existe una buena posibilidad de interbloqueo porque si el hilo 1 adquiere un bloqueo en el objeto String mientras se ejecuta method1 () y el hilo 2 adquiere lock en el objeto Integer mientras se ejecuta method2 () ambos estarán esperando el uno al otro para liberar el bloqueo en Entero y Cadena para avanzar, lo que nunca sucederá.

public void method1() { synchronized (String.class) { System.out.println("Acquired lock on String.class object"); synchronized (Integer.class) { System.out.println("Acquired lock on Integer.class object"); } } } public void method2() { synchronized (Integer.class) { System.out.println("Acquired lock on Integer.class object"); synchronized (String.class) { System.out.println("Acquired lock on String.class object"); } } }


Tal vez una situación bancaria simple.

class Account { double balance; void withdraw(double amount){ balance -= amount; } void deposit(double amount){ balance += amount; } void transfer(Account from, Account to, double amount){ sync(from); sync(to); from.withdraw(amount); to.deposit(amount); release(to); release(from); } }

Obviamente, si hay dos subprocesos que intentan ejecutar la transferencia ( a, b ) y la transferencia ( b, a ) al mismo tiempo, entonces se producirá un interbloqueo porque intentan adquirir los recursos en orden inverso.

Este código también es ideal para buscar soluciones al punto muerto. ¡Espero que esto ayude!


Un ejemplo de interbloqueo más simple con dos recursos diferentes y dos subprocesos que esperan el uno al otro para liberar recursos. Directamente desde examples.oreilly.com/jenut/Deadlock.java

public class Deadlock { public static void main(String[] args) { // These are the two resource objects we''ll try to get locks for final Object resource1 = "resource1"; final Object resource2 = "resource2"; // Here''s the first thread. It tries to lock resource1 then resource2 Thread t1 = new Thread() { public void run() { // Lock resource 1 synchronized(resource1) { System.out.println("Thread 1: locked resource 1"); // Pause for a bit, simulating some file I/O or something. // Basically, we just want to give the other thread a chance to // run. Threads and deadlock are asynchronous things, but we''re // trying to force deadlock to happen here... try { Thread.sleep(50); } catch (InterruptedException e) {} // Now wait ''till we can get a lock on resource 2 synchronized(resource2) { System.out.println("Thread 1: locked resource 2"); } } } }; // Here''s the second thread. It tries to lock resource2 then resource1 Thread t2 = new Thread() { public void run() { // This thread locks resource 2 right away synchronized(resource2) { System.out.println("Thread 2: locked resource 2"); // Then it pauses, for the same reason as the first thread does try { Thread.sleep(50); } catch (InterruptedException e) {} // Then it tries to lock resource1. But wait! Thread 1 locked // resource1, and won''t release it ''till it gets a lock on // resource2. This thread holds the lock on resource2, and won''t // release it ''till it gets resource1. We''re at an impasse. Neither // thread can run, and the program freezes up. synchronized(resource1) { System.out.println("Thread 2: locked resource 1"); } } } }; // Start the two threads. If all goes as planned, deadlock will occur, // and the program will never exit. t1.start(); t2.start(); } }


Un ejemplo en el que puedo pensar es el escenario Table, Linterna y Baterías. Imagine una linterna y un par de baterías colocadas encima de una mesa. Si fueras a caminar a esta mesa y tomas las pilas mientras otra persona tiene la linterna, ambos se verán forzados a mirarse fijamente unos a otros mientras esperan a que primero coloquen el objeto en la mesa. Este es un ejemplo de punto muerto. Usted y la persona esperan recursos, pero ninguno de ustedes está renunciando a sus recursos.

De forma similar, en un programa, el punto muerto ocurre cuando dos o más hilos (usted y la otra persona) esperan que se liberen dos o más bloqueos (linterna y baterías) y las circunstancias del programa son tales que los bloqueos nunca se liberan ( ambos tienen una pieza del rompecabezas).

Si conoces Java, así es como puedes representar este problema:

import java.util.concurrent.locks.*; public class Deadlock1 { public static class Table { private static Lock Flashlight = new ReentrantLock(); private static Lock Batteries = new ReentrantLock(); public static void giveFlashLightAndBatteries() { try { Flashlight.lock(); Batteries.lock(); System.out.println("Lights on"); } finally { Batteries.unlock(); Flashlight.unlock(); } } public static void giveBatteriesAndFlashLight() { try { Batteries.lock(); Flashlight.lock(); System.out.println("Lights on"); } finally { Flashlight.unlock(); Batteries.unlock(); } } } public static void main(String[] args) { // This thread represents person one new Thread(new Runnable() { public void run() { Table.giveFlashLightAndBatteries(); } }).start(); // This thread represents person two new Thread(new Runnable() { public void run() { Table.giveBatteriesAndFlashLight(); } }).start(); } }

Si ejecuta este ejemplo, notará que a veces las cosas funcionan bien y correctamente. Pero a veces tu programa simplemente no imprime nada. Esto se debe a que una persona tiene las baterías mientras que otra tiene la linterna, lo que evita que enciendan la linterna y provoquen un punto muerto.

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:

public class Deadlock2 { public static class Loop { private static boolean done = false; public static synchronized void startLoop() throws InterruptedException { while(!done) { Thread.sleep(1000); System.out.println("Not done"); } } public static synchronized void stopLoop() { done = true; } } public static void main(String[] args) { // This thread starts the loop new Thread(new Runnable() { public void run() { try { Loop.startLoop(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); // This thread stops the loop new Thread(new Runnable() { public void run() { Loop.stopLoop(); } }).start(); } }

Este ejemplo puede imprimir ''No hecho'' una y otra vez o nunca puede imprimir ''No hecho'' en absoluto. Lo primero sucede porque el primer hilo adquiere el bloqueo de clase y nunca lo libera impidiendo que el segundo hilo acceda a ''stopLoop''. Y lo último sucede porque el segundo subproceso comenzó antes del primer subproceso, lo que provocó que la variable ''hecho'' fuera verdadera antes de que se ejecute el primer subproceso.


Uno de los ejemplos simples de interbloqueo que he encontrado.

public class SimpleDeadLock { public static Object l1 = new Object(); public static Object l2 = new Object(); private int index; public static void main(String[] a) { Thread t1 = new Thread1(); Thread t2 = new Thread2(); t1.start(); t2.start(); } private static class Thread1 extends Thread { public void run() { synchronized (l1) { System.out.println("Thread 1: Holding lock 1..."); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println("Thread 1: Waiting for lock 2..."); synchronized (l2) { System.out.println("Thread 2: Holding lock 1 & 2..."); } } } } private static class Thread2 extends Thread { public void run() { synchronized (l2) { System.out.println("Thread 2: Holding lock 2..."); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println("Thread 2: Waiting for lock 1..."); synchronized (l1) { System.out.println("Thread 2: Holding lock 2 & 1..."); } } } } }


A sneaky way to deadlock with just a single thread is to try to lock the same (non-recursive) mutex twice. This might not be the simple example you were looking for, but sure enough I encountered such cases already.

#include <mutex> #include <iostream> int main() { std::mutex m; m.lock(); m.lock(); std::cout << "Expect never to get here because of a deadlock!"; }


I have created an ultra Simple Working DeadLock Example:-

package com.thread.deadlock; public class ThreadDeadLockClient { public static void main(String[] args) { ThreadDeadLockObject1 threadDeadLockA = new ThreadDeadLockObject1("threadDeadLockA"); ThreadDeadLockObject2 threadDeadLockB = new ThreadDeadLockObject2("threadDeadLockB"); new Thread(new Runnable() { @Override public void run() { threadDeadLockA.methodA(threadDeadLockB); } }).start(); new Thread(new Runnable() { @Override public void run() { threadDeadLockB.methodB(threadDeadLockA); } }).start(); } } package com.thread.deadlock; public class ThreadDeadLockObject1 { private String name; ThreadDeadLockObject1(String name){ this.name = name; } public synchronized void methodA(ThreadDeadLockObject2 threadDeadLockObject2) { System.out.println("In MethodA "+" Current Object--> "+this.getName()+" Object passed as parameter--> "+threadDeadLockObject2.getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } threadDeadLockObject2.methodB(this); } public String getName() { return name; } public void setName(String name) { this.name = name; } } package com.thread.deadlock; public class ThreadDeadLockObject2 { private String name; ThreadDeadLockObject2(String name){ this.name = name; } public synchronized void methodB(ThreadDeadLockObject1 threadDeadLockObject1) { System.out.println("In MethodB "+" Current Object--> "+this.getName()+" Object passed as parameter--> "+threadDeadLockObject1.getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } threadDeadLockObject1.methodA(this); } public String getName() { return name; } public void setName(String name) { this.name = name; } }

In the above example 2 threads are executing the synchronized methods of two different objects. Synchronized methodA is called by object threadDeadLockA and synchronized methodB is called by object threadDeadLockB. In methodA a reference of threadDeadLockB is passed and in methodB a reference of threadDeadLockA is passed. Now each thread tries to get lock on the another object. In methodA the thread who is holding a lock on threadDeadLockA is trying to get lock on object threadDeadLockB and similarly in methodB the thread who is holding a lock on threadDeadLockB is trying to get lock on threadDeadLockA. Thus both the threads will wait forever creating a deadlock.


Let me explain more clearly using an example having more than 2 threads.

Let us say you have n threads each holding locks L1, L2, ..., Ln respectively. Now let''s say, starting from thread 1, each thread tries to acquire its neighbour thread''s lock. So, thread 1 gets blocked for trying to acquire L2 (as L2 is owned by thread 2), thread 2 gets blocked for L3 and so on. The thread n gets blocked for L1. This is now a deadlock as no thread is able to execute.

class ImportantWork{ synchronized void callAnother(){ } synchronized void call(ImportantWork work) throws InterruptedException{ Thread.sleep(100); work.callAnother(); } } class Task implements Runnable{ ImportantWork myWork, otherWork; public void run(){ try { myWork.call(otherWork); } catch (InterruptedException e) { } } } class DeadlockTest{ public static void main(String args[]){ ImportantWork work1=new ImportantWork(); ImportantWork work2=new ImportantWork(); ImportantWork work3=new ImportantWork(); Task task1=new Task(); task1.myWork=work1; task1.otherWork=work2; Task task2=new Task(); task2.myWork=work2; task2.otherWork=work3; Task task3=new Task(); task3.myWork=work3; task3.otherWork=work1; new Thread(task1).start(); new Thread(task2).start(); new Thread(task3).start(); } }

In the above example, you can see that there are three threads holding Runnable s task1, task2, and task3. Before the statement sleep(100) the threads acquire the three work objects'' locks when they enter the call() method (due to the presence of synchronized ). But as soon as they try to callAnother() on their neighbour thread''s object, they are blocked, leading to a deadlock, because those objects'' locks have already been taken.


CountDownLatch countDownLatch = new CountDownLatch(1); ExecutorService executorService = ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(() -> { Future<?> future = executorService.submit(() -> { System.out.println("generated task"); }); countDownLatch.countDown(); try { future.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }); countDownLatch.await(); executorService.shutdown();


package ForkBlur; public class DeadLockTest { public static void main(String args[]) { final DeadLockTest t1 = new DeadLockTest(); final DeadLockTest t2 = new DeadLockTest(); Runnable r1 = new Runnable() { @Override public void run() { try { synchronized (t1) { System.out .println("r1 has locked t1, now going to sleep"); Thread.sleep(100); System.out .println("r1 has awake , now going to aquire lock for t2"); synchronized (t2) { Thread.sleep(100); } } } catch (Exception e) { e.printStackTrace(); } } }; Runnable r2 = new Runnable() { @Override public void run() { try { synchronized (t2) { System.out .println("r2 has aquire the lock of t2 now going to sleep"); Thread.sleep(100); System.out .println("r2 is awake , now going to aquire the lock from t1"); synchronized (t1) { Thread.sleep(100); } } } catch (Exception e) { e.printStackTrace(); } } }; new Thread(r1).start(); new Thread(r2).start(); } }


package test.concurrent; public class DeadLockTest { private static long sleepMillis; private final Object lock1 = new Object(); private final Object lock2 = new Object(); public static void main(String[] args) { sleepMillis = Long.parseLong(args[0]); DeadLockTest test = new DeadLockTest(); test.doTest(); } private void doTest() { Thread t1 = new Thread(new Runnable() { public void run() { lock12(); } }); Thread t2 = new Thread(new Runnable() { public void run() { lock21(); } }); t1.start(); t2.start(); } private void lock12() { synchronized (lock1) { sleep(); synchronized (lock2) { sleep(); } } } private void lock21() { synchronized (lock2) { sleep(); synchronized (lock1) { sleep(); } } } private void sleep() { try { Thread.sleep(sleepMillis); } catch (InterruptedException e) { e.printStackTrace(); } } } To run the deadlock test with sleep time 1 millisecond: java -cp . test.concurrent.DeadLockTest 1


public class DeadLock { public static void main(String[] args) { Object resource1 = new Object(); Object resource2 = new Object(); SharedObject s = new SharedObject(resource1, resource2); TestThread11 t1 = new TestThread11(s); TestThread22 t2 = new TestThread22(s); t1.start(); t2.start(); } } class SharedObject { Object o1, o2; SharedObject(Object o1, Object o2) { this.o1 = o1; this.o2 = o2; } void m1() { synchronized(o1) { System.out.println("locked on o1 from m1()"); synchronized(o2) { System.out.println("locked on o2 from m1()"); } } } void m2() { synchronized(o2) { System.out.println("locked on o2 from m2()"); synchronized(o1) { System.out.println("locked on o1 from m2()"); } } } } class TestThread11 extends Thread { SharedObject s; TestThread11(SharedObject s) { this.s = s; } public void run() { s.m1(); } } class TestThread22 extends Thread { SharedObject s; TestThread22(SharedObject s) { this.s = s; } public void run() { s.m2(); } }


public class DeadLock { public static void main(String[] args) throws InterruptedException { Thread mainThread = Thread.currentThread(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { mainThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread1.start(); thread1.join(); } }


public class DeadlockProg { /** * @Gowtham Chitimi Reddy IIT(BHU); */ public static void main(String[] args) { // TODO Auto-generated method stub final Object ob1 = new Object(); final Object ob2 = new Object(); Thread t1 = new Thread(){ public void run(){ synchronized(ob1){ try{ Thread.sleep(100); } catch(InterruptedException e){ System.out.println("Error catched"); } synchronized(ob2){ } } } }; Thread t2 = new Thread(){ public void run(){ synchronized(ob2){ try{ Thread.sleep(100); } catch(InterruptedException e){ System.out.println("Error catched"); } synchronized(ob1){ } } } }; t1.start(); t2.start(); } }