[FIXED] Warum der Deadlock mit Thread.Sleep() nicht funktioniert

Ausgabe

Der Code verwendet Java 8:

public class MustDeadLock {
    private static final Object obj1 = new Object();
    private static final Object obj2 = new Object();

    public static void main(String[] args) {
        mockDeadLock();
    }

    public static void mockDeadLock() {

        CompletableFuture cf1 = CompletableFuture.runAsync(() -> {
            synchronized (obj1) {
                System.out.println("thread A got lock: obj1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("thread A ready to get the rest lock");
                synchronized (obj2) {
                    System.out.println("thread A got all locks");
                }
            }
        });

        CompletableFuture cf2 = CompletableFuture.runAsync(() -> {
            synchronized (obj2) {
                System.out.println("thread B got lock: obj2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("thread B ready to get the rest lock");
                synchronized (obj1) {
                    System.out.println("thread B got all locks");
                }
            }
        });

        CompletableFuture.allOf(cf1, cf2);

        System.out.println("program ready to terminate");
    }
}

Ich frage mich warum

System.out.println("thread A ready to get the rest lock");

und

System.out.println("thread B ready to get the rest lock");)

nicht hingerichtet werden.

Warum wird nur gedruckt:

thread B got lock: obj2
thread A got lock: obj1
program ready to terminate

und dann das Programm beenden statt blockieren?

Lösung

Ganz einfach, weil Ihr Haupt-Thread die Ausführung fortsetzt, während die anderen Threads schlafen.

Wenn Sie warten möchten, bis diese Threads abgeschlossen sind, bevor Sie mit der Ausführung fortfahren, können Sie ihnen beispielsweise vor dem Ende der Methode beitreten:

    // rest of the program
    cf1.join();
    cf2.join();
    System.out.println("program ready to terminate");

Dies wird gedruckt:

    thread B got lock: obj2
    thread A got lock: obj1
    thread B ready to get the rest lock
    thread A ready to get the rest lock

Dadurch wird der Deadlock erzeugt und das Programm wird niemals beendet.


Beantwortet von –
J. Felici


Antwort geprüft von –
Candace Johnson (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like