Einfache Deadlock-Beispiele


92

Ich möchte Neulingen das Einfädeln von Deadlocks erklären. Ich habe in der Vergangenheit viele Beispiele für Deadlocks gesehen, einige mit Code und einige mit Abbildungen (wie die berühmten 4 Autos ). Es gibt auch klassische, leicht festgefahrene Probleme wie The Dining Philosophers , aber diese können zu komplex sein, als dass ein echter Neuling sie vollständig erfassen könnte.

Ich suche nach dem einfachsten Codebeispiel, um zu veranschaulichen, was Deadlocks sind. Das Beispiel sollte:

  1. Beziehen Sie sich auf ein "echtes" Programmierszenario, das Sinn macht
  2. Sei sehr kurz, einfach und unkompliziert

Was empfehlen Sie?


Warum nicht die berühmten 4 Autos benutzen, da es mir ziemlich einfach erscheint?
vehomzzz

2
Die 4 Autos sind kein Programmierszenario, und es ist für einen Neuling nicht trivial, ein Problem in die Form der 4 Autos zu abstrahieren. Ich benutze sie, möchte aber ein Programmierszenario zeigen, in dem ein Deadlock auftritt.
Roee Adler

Antworten:


139

Vielleicht eine einfache Banksituation.

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

}

Sollten zwei Threads gleichzeitig versuchen, die Übertragung ( a, b ) und die Übertragung ( b, a ) gleichzeitig auszuführen , tritt ein Deadlock auf, da sie versuchen, die Ressourcen in umgekehrter Reihenfolge abzurufen.

Dieser Code eignet sich auch hervorragend, um nach Lösungen für den Deadlock zu suchen. Hoffe das hilft!


1
Es wäre perfekt, wenn Sie oder jemand anderes die Lösung für dieses Problem geben könnten.
Jacky

2
@ Jacky Lösung für dieses Problem wird von Will Hartung hier gepostet: stackoverflow.com/questions/13326861/avoid-deadlock-example/…
Piotr Chojnacki

2
Ihre Syntax verwirrt mich. Was ist die sync () -Methode? Ich würde verstehen, wenn sync (from); ... release (from); wurden durch synchronisierte (von) {...} ersetzt
Ellen Spertus

1
@espertus synckann so etwas sein wie : sync(Account & a) { a.mutex.lock(); }.
Vladon

1
javaworld.com/article/2075692/java-concurrency/… (Brian Goetz) erklärt die Lösung für dieses Problem.
Lingareddyk

59

Lassen Sie die Natur Deadlock erklären,

Deadlock: Frosch gegen Schlange

"Ich hätte sie gerne getrennte Wege gehen sehen, aber ich war erschöpft", sagte der Fotograf. „Der Frosch war die ganze Zeit versucht, die Schlange abziehen, aber die Schlange nur lassen würde nicht gehen“ .

Geben Sie hier die Bildbeschreibung ein


59
Süß, erklärt aber nicht, wie Deadlocks in einem Programmierkontext auftreten.
Jalf

ok jalf, zumindest hast du die abstimmung gerechtfertigt. Wie auch immer, es ähnelt dem Beispiel "4 Autos". Eine niedliche Darstellung, wie ein Deadlock aussieht.
Nick Dandoulakis

@ Nick Dandoulakis: Hervorragende Bildpräsentation. Bild erklärt das Konzept der Sackgasse
Rasmi Ranjan Nayak

@ NickDandoulakis - Kein gutes Bild Beispiel imho. Einfacher Code wäre hier hilfreich.
Erran Morad

13
Wie soll das NETT sein? Giftschlangen und Frösche fressen sich gegenseitig ab und es ist beängstigend !!!
Vikkyhacks

53

Hier ist ein Codebeispiel aus der Informatikabteilung einer Universität in Taiwan, das ein einfaches Java-Beispiel mit Ressourcensperrung zeigt. Das ist sehr "real" für mich relevant. Code unten:

/**
 * 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();
  }
}

1
Das Problem ist, dass es nicht wirklich ein "reales" Beispiel ist. Es geht um "Ressource 1" und "Ressource 2", und es wäre schön, dies tatsächlich mit einem tatsächlichen Programmierproblem in Verbindung zu bringen (ich meine, direkt in der Praxis verwendbar, in Bezug auf die Problemdomäne usw.)
Jay

7
Gutes Beispiel meiner Meinung nach. Vielen Dank.
James Raitsev

Dieser Code scheint in einigen verschiedenen Büchern veröffentlicht worden zu sein ... stackoverflow.com/a/11338853/112705
Dan J

15

Wenn sowohl method1 () als auch method2 () von zwei oder vielen Threads aufgerufen werden, besteht eine gute Wahrscheinlichkeit eines Deadlocks, da Thread 1 beim Ausführen von method1 () und Thread 2 beim Ausführen von method2 die Sperre für das Integer-Objekt erhält () Beide warten darauf, dass sie die Sperre für Integer und String aufheben, um fortzufahren, was niemals passieren wird.

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

Schnell und einfach. Nett.
user1068352

13

Eines der einfachen Deadlock-Beispiele, auf die ich gestoßen bin.

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

Ich mag dieses Beispiel. Aber warum wird die SimpleDeadLock-Klasse von Thread getrennt? Das ist nicht nötig.
Charmin

1
Dies ist so ziemlich das Gleiche wie diese Antwort: stackoverflow.com/a/1385868/1310566 . Und was private int indexmacht das dort?
Simon Forsberg

6

Hier ist ein einfaches Beispiel in 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();
}

5

Bitte sehen Sie meine Antwort auf diese Frage . Fazit: Wenn zwei Threads zwei verschiedene Ressourcen erwerben müssen und dies in unterschiedlicher Reihenfolge, können Deadlocks auftreten.


2
Ich sehe keinen Sinn darin, die Informationen aus einer anderen Antwort hier zu duplizieren. Ich gehe davon aus, dass Sie diese Antwort selbst bearbeiten können, wenn Sie der Meinung sind, dass sie verbessert werden kann.
DJNA

Ich denke, diese Situation wird als "Locking Inversion" bezeichnet. Nun, ich weiß, dass es Locking Inversion heißt, weil ich es so nenne, aber ich denke, das ist auch der Kunstbegriff dafür :-)
Steve Jessop

4

Ein Beispiel, an das ich denken kann, ist das Szenario mit Tisch, Taschenlampe und Batterien. Stellen Sie sich eine Taschenlampe und ein Paar Batterien auf einem Tisch vor. Wenn Sie zu diesem Tisch gehen und die Batterien greifen, während eine andere Person die Taschenlampe hat, werden Sie beide gezwungen sein, sich unbeholfen anzustarren, während Sie darauf warten, wer ihren Gegenstand zuerst wieder auf den Tisch legt. Dies ist ein Beispiel für einen Deadlock. Sie und die Person warten auf Ressourcen, aber keiner von Ihnen gibt ihre Ressourcen auf.

In ähnlicher Weise tritt in einem Programm ein Deadlock auf, wenn zwei oder mehr Threads (Sie und die andere Person) darauf warten, dass zwei oder mehr Sperren (Taschenlampe und Batterien) freigegeben werden, und die Umstände im Programm so sind, dass die Sperren niemals freigegeben werden ( Sie haben beide ein Puzzleteil).

Wenn Sie Java kennen, können Sie dieses Problem folgendermaßen darstellen:

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

Wenn Sie dieses Beispiel ausführen, werden Sie feststellen, dass die Dinge manchmal gut und korrekt funktionieren. Aber manchmal druckt Ihr Programm einfach nichts. Das liegt daran, dass eine Person die Batterien hat, während eine andere Person die Taschenlampe hat, die verhindert, dass sie die Taschenlampe einschaltet, was zu einem Deadlock führt.

Dieses Beispiel ähnelt dem Beispiel in den Java-Tutorials: http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

Ein weiteres Beispiel ist das Schleifenbeispiel:

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

Dieses Beispiel kann entweder immer wieder "Nicht erledigt" drucken oder es kann niemals "Nicht erledigt" drucken. Der erste geschieht, weil der erste Thread die Klassensperre erhält und sie niemals aufhebt, um zu verhindern, dass der zweite Thread auf 'stopLoop' zugreift. Und das Neueste passiert, weil der zweite Thread vor dem ersten Thread gestartet wurde und die Variable 'done' wahr ist, bevor der erste Thread ausgeführt wird.


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

3

Ich betrachte das Problem der Dining Philosophen jedoch als eines der einfacheren Beispiele für das Anzeigen von Deadlocks, da die 4 Deadlock-Anforderungen durch die Zeichnung leicht veranschaulicht werden können (insbesondere das kreisförmige Warten).

Ich halte Beispiele aus der realen Welt für viel verwirrender für den Neuling, obwohl ich mir momentan kein gutes Szenario aus der realen Welt vorstellen kann (ich bin relativ unerfahren mit der Parallelität in der realen Welt).


3

Ich habe kürzlich festgestellt, dass die Kämpfe zwischen Paaren nichts anderes als ein Stillstand sind. Normalerweise muss einer der Prozesse abstürzen, um ihn zu lösen. Natürlich hat er weniger Priorität (Boy;)).

Hier ist die Analogie ...

Prozess1: Mädchen (G) Prozess2: Junge (B)
Ressource1: Entschuldigung Ressource2: Akzeptieren des eigenen Fehlers

Notwendige Bedingungen:
1. Gegenseitiger Ausschluss: Nur einer von G oder B kann sich gleichzeitig entschuldigen oder einen eigenen Fehler akzeptieren.
2. Halten und warten: Zu einer Zeit hält einer "Sorry" und "Andere". Akzeptieren eines eigenen Fehlers, einer wartet darauf, "Akzeptieren eines eigenen Fehlers", um "Entschuldigung" freizugeben, und der andere wartet auf "Entschuldigung", um das Akzeptieren eines eigenen Fehlers freizugeben.
3. Keine Vorentscheidung: Nicht einmal Gott kann B oder G zwingen, Entschuldigung freizugeben oder eigenen Fehler zu akzeptieren. Und freiwillig? Willst du mich verarschen??
4. Circular Wait: Wieder wartet derjenige, der sich entschuldigt, darauf, dass andere seine eigenen Fehler akzeptieren, und einer, der sich entschuldigt, möchte, dass andere sich zuerst entschuldigen. Es ist also kreisförmig.

Deadlocks treten also auf, wenn alle diese Bedingungen gleichzeitig gelten, und das ist bei einem Zweikampf immer der Fall;)

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


3

Ein weiteres einfaches Deadlock-Beispiel mit zwei verschiedenen Ressourcen und zwei Threads, die darauf warten, dass die Ressourcen freigegeben werden. Direkt von 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();
  }
}

If all goes as planned, deadlock will occur, and the program will never exit.Können wir dieses Beispiel zum guaranteeStillstand bringen?
Erran Morad

Dies ist derselbe Code, den Kyle gepostet hat. Warum drei Jahre nach einer anderen Antwort eine doppelte Antwort hinzufügen? (und warum kommentiere ich es noch drei Jahre später?)
Simon Forsberg

2

Deadlock kann in einer Situation auftreten , wenn ein Girl1zu flirten fehlt mit Guy2, die von einer anderen gefangen ist Girl2, und Girl2mit einem an flirt fehlt , Guy1die durch gefangen wird Girl1. Da beide Mädchen darauf warten, sich gegenseitig zu entleeren, spricht man von einem Deadlock.

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


1

Entscheiden Sie sich für das einfachste Szenario, in dem ein Deadlock auftreten kann, wenn Sie Ihren Schülern das Konzept vorstellen. Dies würde mindestens zwei Threads und mindestens zwei Ressourcen beinhalten (glaube ich). Das Ziel besteht darin, ein Szenario zu entwickeln, in dem der erste Thread eine Sperre für Ressource eins hat und darauf wartet, dass die Sperre für Ressource zwei aufgehoben wird, während Thread zwei gleichzeitig eine Sperre für Ressource zwei hält und darauf wartet die Sperre für Ressource eins, die freigegeben werden soll.

Es spielt keine Rolle, welche Ressourcen zugrunde liegen. Der Einfachheit halber können Sie sie einfach zu einem Dateipaar machen, in das beide Threads schreiben können.

BEARBEITEN: Dies setzt keine andere Kommunikation zwischen Prozessen als die gehaltenen Sperren voraus.


1

Ich fand, dass Deadlock IMHO beim Lesen des Problems der Speisephilosophen etwas schwer zu verstehen ist und tatsächlich mit der Ressourcenzuweisung zusammenhängt. Ich möchte ein einfacheres Beispiel nennen, in dem 2 Krankenschwestern um 3 Ausrüstung kämpfen müssen, um eine Aufgabe zu erledigen. Obwohl es in Java geschrieben ist. Eine einfache lock () -Methode wird erstellt, um zu simulieren, wie der Deadlock auftritt, sodass sie auch in anderen Programmiersprachen angewendet werden kann. http://www.justexample.com/wp/example-of-deadlock/


1

Einfaches Beispiel von 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();
}

}

Ausgabe:

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

1

Hier ist ein einfacher Deadlock in Java. Wir brauchen zwei Ressourcen, um einen Deadlock zu demonstrieren. Im folgenden Beispiel ist eine Ressource die Klassensperre (über die Synchronisierungsmethode) und die andere eine Ganzzahl '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();
    }
}

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

1
Könnten Sie bitte einen Text hinzufügen, um Ihre Antwort zu erläutern?
Kmeixner

1

Hier ist ein einfacher Deadlock in 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;
        }
    }
}

Wenn Sie dies eines Tages über den GUI-Thread aufrufen und ein anderer Thread dies ebenfalls aufruft, kann dies zu einem Deadlock führen. Der andere Thread gelangt zu EndInvoke und wartet darauf, dass der GUI-Thread den Delegaten ausführt, während er die Sperre hält. Der GUI-Thread blockiert dieselbe Sperre und wartet darauf, dass der andere Thread sie freigibt. Dies ist jedoch nicht der Fall, da der GUI-Thread niemals verfügbar ist, um den Delegaten auszuführen, auf den der andere Thread wartet. (Natürlich wird die Sperre hier nicht unbedingt benötigt - und vielleicht auch nicht EndInvoke, aber in einem etwas komplexeren Szenario kann der Anrufer aus anderen Gründen eine Sperre erwerben, was zum gleichen Deadlock führt.)


0
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

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

}

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

0

Ich habe ein ultra Simple Working DeadLock-Beispiel erstellt: -

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

Im obigen Beispiel führen 2 Threads die synchronisierten Methoden von zwei verschiedenen Objekten aus. Die synchronisierte Methode A wird vom Objekt threadDeadLockA aufgerufen, und die synchronisierte Methode B wird vom Objekt threadDeadLockB aufgerufen. In Methode A wird eine Referenz von threadDeadLockB übergeben, und in Methode B wird eine Referenz von threadDeadLockA übergeben. Jetzt versucht jeder Thread, das andere Objekt zu sperren. In Methode A versucht der Thread, der eine Sperre für threadDeadLockA hält, eine Sperre für das Objekt threadDeadLockB zu erhalten, und in Methode B versucht der Thread, der eine Sperre für threadDeadLockB hält, eine Sperre für threadDeadLockA zu erhalten. Somit warten beide Threads ewig und erzeugen einen Deadlock.


0

Lassen Sie mich anhand eines Beispiels mit mehr als 2 Threads klarer erklären .

Angenommen, Sie haben n Threads, die jeweils die Schlösser L1, L2, ..., Ln halten. Angenommen, ab Thread 1 versucht jeder Thread, die Sperre seines Nachbar-Threads zu erlangen. Also wird Thread 1 blockiert, um zu versuchen, L2 zu erhalten (da L2 im Besitz von Thread 2 ist), Thread 2 wird für L3 blockiert und so weiter. Der Thread n wird für L1 blockiert. Dies ist jetzt ein Deadlock, da kein Thread ausgeführt werden kann.

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

Im obigen Beispiel sehen Sie, dass drei Threads Runnables task1, task2 und task3 enthalten. Vor der Anweisung erhalten sleep(100)die Threads die Sperren der drei Arbeitsobjekte, wenn sie in die call()Methode eintreten (aufgrund des Vorhandenseins von synchronized). Sobald sie jedoch versuchen, callAnother()das Objekt ihres Nachbar-Threads zu bearbeiten, werden sie blockiert, was zu einem Deadlock führt, da die Sperren dieser Objekte bereits aufgehoben wurden.


0
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();

0

Eine hinterhältige Möglichkeit, mit nur einem Thread einen Deadlock durchzuführen, besteht darin, denselben (nicht rekursiven) Mutex zweimal zu sperren. Dies ist vielleicht nicht das einfache Beispiel, nach dem Sie gesucht haben, aber ich bin auf solche Fälle bereits gestoßen.

#include <mutex>
#include <iostream>

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

0

Hier ist mein detailliertes Beispiel für einen Deadlock , nachdem ich viel Zeit verbracht habe. Ich hoffe es hilft :)

package deadlock;

public class DeadlockApp {

    String s1 = "hello";
    String s2 = "world";

    Thread th1 = new Thread() {
        public void run() {
            System.out.println("Thread th1 has started");
            synchronized (s1) { //A lock is created internally (holds access of s1), lock will be released or unlocked for s1, only when it exits the block Line #23
                System.out.println("Executing first synchronized block of th1!");
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException ex) {
                    System.out.println("Exception is caught in th1");
                }
                System.out.println("Waiting for the lock to be released from parrallel thread th1");
                synchronized (s2) { //As another has runned parallely Line #32, lock has been created for s2
                    System.out.println(s1 + s2);
                }

            }
            System.out.println("Thread th1 has executed");
        }
    };


    Thread th2 = new Thread() {
        public void run() {
            System.out.println("Thread th2 has started");
            synchronized (s2) { //A lock is created internally (holds access of s2), lock will be released or unlocked for s2, only when it exits the block Line #44
                System.out.println("Executing first synchronized block of th2!");
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException ex) {
                    System.out.println("Exception is caught in th2");
                }
                System.out.println("Waiting for the lock to be released from parrallel thread th2");
                synchronized (s1) { //As another has runned parallely Line #11, lock has been created for s1
                    System.out.println(s1 + s2);
                }

            }
            System.out.println("Thread th2 has executed");
        }
    };

    public static void main(String[] args) {
        DeadlockApp deadLock = new DeadlockApp();
        deadLock.th1.start();
        deadLock.th2.start();
        //Line #51 and #52 runs parallely on executing the program, a lock is created inside synchronized method
        //A lock is nothing but, something like a blocker or wall, which holds access of the variable from being used by others.
        //Locked object is accessible, only when it is unlocked (i.e exiting  the synchronized block)
        //Lock cannot be created for primitive types (ex: int, float, double)
        //Dont forget to add thread.sleep(time) because if not added, then object access will not be at same time for both threads to create Deadlock (not actual runtime with lots of threads) 
        //This is a simple program, so we added sleep90 to create Deadlock, it will execute successfully, if it is removed. 
    }

    //Happy coding -- Parthasarathy S
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.