In Java ist Deadlock eine Multithreading-Situation, in der Thread 1 auf eine Objektsperre von Thread 2 und Thread 2 auf eine Objektsperre von Thread 1 wartet. Hier warten sowohl Thread 1 als auch Thread 2 aufeinander um die Sperre zu lösen. Multithread-Programme in Java können einen Deadlock verursachen, da das Schlüsselwort synchronisiert den ausführenden Thread blockiert, während es auf einen Monitor oder eine Sperre wartet, die mit dem genannten Objekt verknüpft ist. Sehen wir uns in den folgenden Abschnitten die Funktionsweise und Beispiele von Deadlock an.
Starten Sie Ihren kostenlosen Softwareentwicklungskurs
Webentwicklung, Programmiersprachen, Softwaretests und andere
Wie bereits erwähnt, kann die synchronisierte Methode einen bestimmten Teil des Codes sperren. Für jedes Objekt in Java gibt es eine Sperre, und Synchronisierung ist eine Technik zum Sperren einer Funktion oder eines Codeblocks, um sicherzustellen, dass jeweils nur ein Thread auf diese Funktion oder diesen Codeblock zugreifen kann.
Wenn ein bestimmter Thread eine synchronisierte Funktion ausführen muss, versucht er zunächst, die Sperre zu erhalten. Wenn gleichzeitig ein anderer Thread die Sperre bereits erhalten hat, wartet der erste Thread, bis Thread 2 die Sperre aufhebt. Obwohl die Synchronisierung Probleme mit Dateninkonsistenzen verhindert, liegt ein Synchronisierungsproblem vor.
Angenommen, es gibt zwei Threads, „Thread 1“ und „Thread 2“. Thread 1 hat die Sperre von Objekt 1 erreicht, und Thread 2 hat die Sperre von Objekt 2 erreicht. Thread 1, der Methode 1 ausführt, möchte die Sperre für Objekt 2 erreichen. Thread 2 hat jedoch bereits die Sperre für Objekt 2 erreicht.
Darüber hinaus muss Thread 2 auch die Sperre für Objekt 1 erreichen; Thread 1 hat jedoch eine Sperre für Objekt 1. Hier können beide Threads, Thread 1 und Thread 2, ihre Ausführung nicht abschließen und warten ewig auf die Sperre. Diese Situation wird Deadlock genannt.
Im Folgenden finden Sie die genannten Beispiele:
Java-Programm zur Implementierung von Deadlock.
Code:
public class DeadLockExample { //main method public static void main(String[] args) throws InterruptedException { //create three objects 1, 2 and 3 Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); //create three threads 1, 2 and 3 Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1"); Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2"); Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3"); //start thread 1 th1.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); //start thread 2 th2.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); //start thread 3 th3.start(); } } class SynchronizationThread implements Runnable { private Object o1; private Object o2; public SynchronizationThread(Object o1, Object o2){ this.o1=o1; this.o2=o2; } //function run @Override public void run() { //store the name of the thread String nm = Thread.currentThread().getName(); System.out.println( nm + " attaining lock on "+ o1 ) ; synchronized (o1) { System.out.println( nm + " attained lock on "+ o1 ) ; work(); System.out.println( nm + " attaining lock on "+ o2 ) ; synchronized (o2) { System.out.println( nm + " attained lock on "+ o2 ); work(); } System.out.println( nm + " released lock on "+ o2 ) ; } System.out.println( nm + " released lock on "+ o1 ) ; System.out.println( nm + " completed execution.") ; } //function work private void work() { try { //thread sleeps Thread.sleep(30000); } //catch the exception catch (InterruptedException exc) { exc.printStackTrace(); } } }
Ausgabe:
In diesem Programm teilen sich 3 laufende Threads eine Ressource und sie werden auf eine Weise ausgeführt, die eine Sperre für Objekt 1 erreicht, aber wenn sie versucht, eine Sperre für Objekt 2 zu erreichen, wechselt sie in einen Wartezustand. Um einen Deadlock zu verhindern, können Sie den Code wie folgt umschreiben.
Code:
public class DeadLockExample { public static void main(String[] args) throws InterruptedException { Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1"); Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2"); Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3"); //start thread 1, 2 and 3 th1.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); th2.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); th3.start(); } } class SynchronizationThread implements Runnable{ private Object o1; private Object o2; public SynchronizationThread(Object o1, Object o2){ this.o1=o1; this.o2=o2; } //function run @Override public void run() { //store the name of the thread String nm = Thread.currentThread().getName(); System.out.println( nm + " attaining lock on "+ o1 ) ; synchronized (o1) { System.out.println( nm + " attained lock on "+ o1 ) ; work(); } System.out.println( nm + " released lock on "+ o1 ) ; System.out.println( nm + " acquiring lock on " + o2 ); synchronized (o2) { System.out.println( nm + " attained lock on "+ o2 ); work(); } System.out.println( nm + " released lock on "+ o2 ) ; System.out.println( nm + " released lock on "+ o1 ) ; System.out.println( nm + " completed execution.") ; } //function work private void work() { try { //thread sleeps Thread.sleep(30000); } //catch the exception catch (InterruptedException exc) { exc.printStackTrace(); } } }
Ausgabe:
Im Folgenden finden Sie die Richtlinien, die dabei helfen, Blockaden zu vermeiden.
Verschachtelte Sperren sind eine der häufigsten Ursachen für Deadlocks. Sperren Sie keine andere Ressource, wenn diese bereits über eine verfügt, um einen Deadlock zu vermeiden. Wenn der Benutzer nur mit einem Objekt arbeitet, ist es unmöglich, einen Deadlock zu verursachen.
Es wird empfohlen, nur die notwendigen Ressourcen zu sperren. Einige Benutzer versuchen jedoch möglicherweise, Ressourcen zu sperren, auch wenn dies nicht erforderlich ist.
Ein Deadlock tritt auf, wenn zwei Threads mithilfe von Thread-Join auf unbestimmte Zeit darauf warten, dass der andere abgeschlossen wird. Wenn der Thread auf den Abschluss anderer Threads warten muss, empfiehlt es sich, Join mit der maximalen Zeitspanne zu verwenden, die auf den Abschluss des Threads gewartet werden muss.
Das obige ist der detaillierte Inhalt vonDeadlock in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!