Simple Deadlock Exemples

Je voudrais expliquer les impasses des threads aux débutants. J’ai vu beaucoup d’exemples de blocages dans le passé, certains utilisant du code et d’autres utilisant des illustrations (comme les fameuses 4 voitures ). Il y a aussi des problèmes classiques facilement bloqués comme The Dining Philosophers , mais ceux-ci peuvent être trop complexes pour un vrai débutant.

Je cherche l’exemple de code le plus simple pour illustrer ce que sont les impasses. L’exemple devrait:

  1. Se rapporter à un “vrai” scénario de programmation qui a du sens
  2. Soyez très court, simple et direct

Que recommandez-vous?

    Peut-être une simple situation bancaire.

    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); } } 

    Évidemment, si deux threads tentent d’exécuter simultanément transfer ( a, b ) et transfer ( b, a ), un blocage se produit car ils essaient d’acquérir les ressources dans l’ordre inverse.

    Ce code est également idéal pour examiner les solutions à l’impasse. J’espère que cela t’aides!

    Laissez la nature expliquer l’impasse,

    Deadlock: Frog vs. Snake

    “J’adorerais les voir se séparer, mais j’étais épuisé”, a déclaré le photographe. “La grenouille essayait tout le temps de retirer le serpent, mais le serpent ne lâchait pas” .

    entrer la description de l'image ici

    Voici un exemple de code du département informatique d’une université taïwanaise montrant un exemple simple de Java avec locking des ressources. C’est très “réel” pertinent pour moi. Code ci-dessous:

     /** * 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(Ssortingng[] 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 sortinges 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 sortinges 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 sortinges 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(); } } 

    Si method1 () et method2 () sont tous deux appelés par deux ou plusieurs threads, il y a de fortes chances de blocage car si le thread 1 acquiert un object Ssortingng lors de l’exécution de method1 () et que le thread 2 acquiert un object Integer () les deux attendent l’un de l’autre pour libérer le verrou sur Integer et Ssortingng pour continuer plus loin, ce qui n’arrivera jamais.

     public void method1() { synchronized (Ssortingng.class) { System.out.println("Acquired lock on Ssortingng.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 (Ssortingng.class) { System.out.println("Acquired lock on Ssortingng.class object"); } } } 

    L’un des exemples simples d’impasse que j’ai rencontrés.

     public class SimpleDeadLock { public static Object l1 = new Object(); public static Object l2 = new Object(); private int index; public static void main(Ssortingng[] 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..."); } } } } } 

    Voici un exemple simple en C ++ 11.

     #include  // mutex #include  // cout #include  // getchar #include  // this_thread, yield #include  // async #include  // 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 l1(_m1); this_thread::yield(); // hint to reschedule this_thread::sleep_for( chrono::seconds(1) ); unique_lock l2(_m2 ); } void func21() { unique_lock l2(_m2); this_thread::yield(); // hint to reschedule this_thread::sleep_for( chrono::seconds(1) ); unique_lock l1(_m1); } int main( int argc, char* argv[] ) { async(func12); func21(); cout << "All done!"; // this won't be executed because of deadlock getchar(); } 

    S’il vous plaît voir ma réponse à cette question . En bout de ligne, chaque fois que deux threads ont besoin d’acquérir deux ressources différentes, et le font dans des ordres différents, vous pouvez obtenir des blocages.

    Un exemple auquel je peux penser est le scénario Table, lampe de poche et stacks. Imaginez une lampe de poche et une paire de stacks placées sur une table. Si vous devez marcher vers cette table et attraper les stacks pendant qu’une autre personne a la lampe de poche, vous serez obligés de vous regarder maladroitement en attendant de voir qui va placer son object sur la table. C’est un exemple d’impasse. Vous et la personne attendez des ressources, mais aucun d’entre vous n’abandonne ses ressources.

    De même, dans un programme, un blocage survient lorsque deux threads ou plus (vous et l’autre personne) attendent la libération de deux verrous (lampe de poche et stacks) et que les circonstances du programme ne libèrent jamais les verrous ( vous avez tous les deux une pièce du puzzle).

    Si vous connaissez java, voici comment vous pouvez représenter ce problème:

     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(Ssortingng[] 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 vous exécutez cet exemple, vous remarquerez que parfois les choses fonctionnent bien et correctement. Mais parfois, votre programme ne va rien imprimer. Cela est dû au fait qu’une personne a les stacks pendant qu’une autre personne a la lampe de poche, ce qui les empêche d’allumer la lampe de poche et de provoquer une impasse.

    Cet exemple est similaire à l’exemple donné par les didacticiels Java: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

    Un autre exemple est l’exemple de la boucle:

     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(Ssortingng[] 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(); } } 

    Cet exemple peut soit imprimer «pas fait» encore et encore ou il ne peut jamais imprimer «pas fait» du tout. La première se produit parce que le premier thread acquiert le verrou de classe et ne le libère jamais, empêchant le second thread d’accéder à «stopLoop». Et le dernier se produit parce que le deuxième thread a démarré avant le premier thread, ce qui a pour effet que la variable “done” soit vraie avant l’exécution du premier thread.

    Je considère le problème des philosophes de la restauration comme l’un des exemples les plus simples pour montrer des impasses, car les 4 exigences de blocage peuvent être facilement illustrées par le dessin (en particulier l’attente circulaire).

    Je considère que les exemples du monde réel sont beaucoup plus déroutants pour les débutants, même si je ne peux pas penser à un bon scénario du monde réel en ce moment (je suis relativement inexpérimenté en matière de concurrence réelle).

    Je me suis récemment rendu compte que les combats entre couples ne sont rien d’autre qu’une impasse. En général, l’un des processus doit s’écraser pour le résoudre, bien sûr, c’est le cas moins prioritaire (Boy;)).

    Voici l’analogie …

    Processus1: Fille (G) Processus2: Garçon (B)
    Resource1: désolé Resource2: accepter sa propre erreur

    Conditions nécessaires:
    1. Exclusion mutuelle: Un seul des membres G ou B peut dire désolé ou accepter sa propre erreur à la fois.
    2. Attendez et attendez: à un moment, on tient Désolé et autre Accepter sa propre erreur, on attend Accepter sa propre erreur pour libérer désolé, et autre attend désolé de libérer en acceptant sa propre erreur.
    3. Pas de préemption: même Dieu ne peut pas forcer B ou G à libérer Désolé ou accepter sa propre erreur. Et volontairement? Vous plaisantez j’espère??
    4. Circulaire Attendez: Encore une fois, celui qui regrette attend que l’autre accepte ses propres erreurs, et qu’une personne qui accepte accepte ses propres erreurs veut que l’autre dise d’abord pardon. Donc c’est circulaire.

    Donc, des impasses surviennent quand toutes ces conditions sont en vigueur au même moment, et c’est toujours le cas dans une dispute de couple;)

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

    Un autre exemple d’interblocage simple avec deux ressources différentes et deux threads en attente l’un de l’autre pour libérer la ressource. Directement à partir de examples.oreilly.com/jenut/Deadlock.java

      public class Deadlock { public static void main(Ssortingng[] 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 sortinges 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 sortinges 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 sortinges 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(); } } 
     public class DeadLock { public static void main(Ssortingng[] 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(); } } 

    Le problème des producteurs-consommateurs et le problème des philosophes de la restauration sont probablement aussi simples que cela va arriver. Il y a aussi un pseudocode qui l’illustre. Si ceux-ci sont trop complexes pour un débutant, ils feraient mieux de les saisir.

    Optez pour le scénario simpliste dans lequel une impasse peut survenir lors de la présentation du concept à vos élèves. Cela impliquerait un minimum de deux threads et un minimum de deux ressources (je pense). Le but étant de créer un scénario dans lequel le premier thread a un verrou sur la ressource un et attend la libération du verrou sur la ressource deux, tandis que le thread deux maintient un verrou sur la ressource deux et attend le verrou sur la ressource une à libérer.

    Peu importe les ressources sous-jacentes; Pour simplifier, vous pouvez simplement en faire une paire de fichiers sur lesquels les deux threads peuvent écrire.

    EDIT: Cela suppose qu’aucune communication inter-processus autre que les verrous détenus.

    J’ai trouvé un peu difficile à comprendre lors de la lecture du problème des philosophes de la restauration, impasse IMHO est en réalité liée à l’allocation des ressources. J’aimerais partager un exemple plus simple où 2 infirmières doivent se battre pour 3 équipements afin de mener à bien une tâche. Bien que cela soit écrit en Java. Une méthode simple lock () est créée pour simuler le blocage, de sorte qu’elle peut s’appliquer également dans d’autres langages de programmation. http://www.justexample.com/wp/example-of-deadlock/

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

     public class Deadlock { public static void printMessage(Ssortingng message) { System.out.println(Ssortingng.format("%s %s ", Thread.currentThread().getName(), message)); } private static class Friend { private Ssortingng name; public Friend(Ssortingng 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(Ssortingng[] 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(); } } 

    Sortie:

     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 

    Dump de fil:

     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 ComstackrThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f47240c6800 nid=0x3793 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 ComstackrThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f47240c4000 nid=0x3792 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 ComstackrThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f47240c2800 nid=0x3791 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 ComstackrThread0" #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 

    Voici une simple impasse en Java. Nous avons besoin de deux ressources pour démontrer une impasse. Dans l’exemple ci-dessous, une ressource est la classe lock (via la méthode sync) et l’autre est un entier ‘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(Ssortingng[] 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(); } } 

    Le blocage peut se produire dans le cas où une Girl1 veut flirter avec Guy2 , qui est prise par une autre Girl2 , et Girl2 veut flirter avec un Guy1 pris par Girl1 . Depuis, les deux filles attendent de se vider, la condition est appelée impasse.

     class OuchTheGirls { public static void main(Ssortingng[] args) { final Ssortingng resource1 = "Guy1"; final Ssortingng resource2 = "Guy2"; // Girl1 sortinges 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 sortinges 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(); } } 
     public class DeadLock { public static void main(Ssortingng[] 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(); } } 

    Voici une simple impasse en C #.

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

    Si, un jour, vous appelez cela depuis le thread d’interface graphique, et qu’un autre thread l’appelle également, vous risquez de vous bloquer. L’autre thread arrive à EndInvoke, attend que le thread de l’interface graphique exécute le délégué tout en maintenant le verrou. Le thread d’interface graphique se bloque sur le même verrou en attendant que l’autre thread le libère – ce qui ne sera pas le cas car le thread d’interface graphique ne sera jamais disponible pour exécuter le délégué que l’autre thread attend. (bien sûr, le verrou n’est pas ssortingctement nécessaire – ni EndInvoke, mais dans un scénario légèrement plus complexe, l’appelant peut acquérir un verrou pour d’autres raisons, entraînant le même blocage.)

     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(Ssortingng[] 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 DeadlockProg { /** * @Gowtham Chitimi Reddy IIT(BHU); */ public static void main(Ssortingng[] 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(); } } 
     package ForkBlur; public class DeadLockTest { public static void main(Ssortingng 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(); } } 

    J’ai créé un exemple ultra simple de travail DeadLock: –

     package com.thread.deadlock; public class ThreadDeadLockClient { public static void main(Ssortingng[] 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 Ssortingng name; ThreadDeadLockObject1(Ssortingng 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 Ssortingng getName() { return name; } public void setName(Ssortingng name) { this.name = name; } } package com.thread.deadlock; public class ThreadDeadLockObject2 { private Ssortingng name; ThreadDeadLockObject2(Ssortingng 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 Ssortingng getName() { return name; } public void setName(Ssortingng 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 sortinges 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 sortinges 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(Ssortingng 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(); 

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