Heim  >  Artikel  >  Java  >  Lösungen für Deadlocks, die bei der Java-Entwicklung auftreten

Lösungen für Deadlocks, die bei der Java-Entwicklung auftreten

Y2J
Y2JOriginal
2017-05-05 14:56:111308Durchsuche

In diesem Artikel werden hauptsächlich detaillierte Erklärungen und einfache Beispiele für Java-Multithread-Deadlocks vorgestellt.

Deadlock ist eine Situation, in der mehrere Threads gleichzeitig blockiert werden Alle warten auf die Freigabe einer Ressource. Da der Thread auf unbestimmte Zeit blockiert ist, kann das Programm nicht ordnungsgemäß beendet werden.

Vier notwendige Bedingungen für einen Java-Deadlock:

1> sich gegenseitig ausschließende Nutzung, d. h. wenn eine Ressource von einem Thread verwendet (belegt) wird, von einem anderen Der Thread kann

2> nicht verwenden und ist nicht präemptiv. Der Ressourcenanforderer kann die Ressource nicht zwangsweise vom Ressourcenbesitzer beschlagnahmen, und die Ressource kann nur aktiv vom Ressourcenbesitzer freigegeben werden.

3> Anfordern und Verwalten, das heißt, wenn der Ressourcenanforderer andere Ressourcen anfordert und gleichzeitig Kameraden in den ursprünglichen Ressourcen beibehält.

4> Schleife Warten, das heißt, es gibt eine Warteschlange : P1 belegt die Ressourcen von P2, P2 belegt die Ressourcen von P3 und P3 belegt die Ressourcen von P1. Dadurch entsteht eine Warteschleife.

Wenn die oben genannten vier Bedingungen zutreffen, entsteht ein Deadlock. Im Falle eines Deadlocks verschwindet der Deadlock natürlich, wenn eine der oben genannten Bedingungen verletzt wird. Lassen Sie uns Java-Code verwenden, um das Auftreten eines Deadlocks zu simulieren.


Die Möglichkeiten zur Lösung des Deadlock-Problems sind: Eine besteht darin, synchronisiert zu verwenden, und die andere darin, die explizite Sperrimplementierung von Lock zu verwenden.


Und wenn die Sperre unsachgemäß verwendet wird und mehrere

Objekte gleichzeitig gesperrt werden, kommt es zu einer Deadlock-Situation wie folgt:

/*
 author by w3cschool.cc
 LockTest.java
 */
import java.util.Date;
public class LockTest {
  public static String obj1 = "obj1";
  public static String obj2 = "obj2";
  public static void main(String[] args) {
   LockA la = new LockA();
   new Thread(la).start();
   LockB lb = new LockB();
   new Thread(lb).start();
  }
}
class LockA implements Runnable{
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockA 开始执行");
     while(true){
      synchronized (LockTest.obj1) {
        System.out.println(new Date().toString() + " LockA 锁住 obj1");
        Thread.sleep(3000); // 此处等待是给B能锁住机会
        synchronized (LockTest.obj2) {
         System.out.println(new Date().toString() + " LockA 锁住 obj2");
         Thread.sleep(60 * 1000); // 为测试,占用了就不放
        }
      }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}
class LockB implements Runnable{
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockB 开始执行");
     while(true){
      synchronized (LockTest.obj2) {
        System.out.println(new Date().toString() + " LockB 锁住 obj2");
        Thread.sleep(3000); // 此处等待是给A能锁住机会
        synchronized (LockTest.obj1) {
         System.out.println(new Date().toString() + " LockB 锁住 obj1");
         Thread.sleep(60 * 1000); // 为测试,占用了就不放
        }
      }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}

Das Ausgabeergebnis der Ausführung des obigen Codes ist:

Tue May 05 10:51:06 CST 2015 LockB 开始执行
Tue May 05 10:51:06 CST 2015 LockA 开始执行
Tue May 05 10:51:06 CST 2015 LockB 锁住 obj2
Tue May 05 10:51:06 CST 2015 LockA 锁住 obj1
Zu diesem Zeitpunkt tritt ein Deadlock auf.


Um dieses Problem zu lösen, verwenden wir keine explizite Entsperrung, sondern Semaphoren, um es zu steuern.


Das Semaphor kann steuern, wie viele Threads auf die Ressource zugreifen können. Hier geben wir an, dass nur ein Thread darauf zugreifen kann, was dem Sperren ähnelt. Das Semaphor kann den Timeout-Zeitraum für die Erfassung angeben, und wir können basierend auf diesem Timeout-Zeitraum weitere Verarbeitungen durchführen.


Wenn Sie es nicht erfolgreich erhalten, können Sie es normalerweise erneut versuchen oder die Anzahl der Versuche angeben, oder Sie können

sofort beenden.

Sehen Sie sich den folgenden Code an:

/*
 author by w3cschool.cc
 UnLockTest.java
 */
import java.util.Date;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class UnLockTest {
  public static String obj1 = "obj1";
  public static final Semaphore a1 = new Semaphore(1);
  public static String obj2 = "obj2";
  public static final Semaphore a2 = new Semaphore(1);
  public static void main(String[] args) {
   LockAa la = new LockAa();
   new Thread(la).start();
   LockBb lb = new LockBb();
   new Thread(lb).start();
  }
}
class LockAa implements Runnable {
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockA 开始执行");
     while (true) {
      if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
        System.out.println(new Date().toString() + " LockA 锁住 obj1");
        if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
         System.out.println(new Date().toString() + " LockA 锁住 obj2");
         Thread.sleep(60 * 1000); // do something
        }else{
         System.out.println(new Date().toString() + "LockA 锁 obj2 失败");
        }
      }else{
        System.out.println(new Date().toString() + "LockA 锁 obj1 失败");
      }
      UnLockTest.a1.release(); // 释放
      UnLockTest.a2.release();
      Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}
class LockBb implements Runnable {
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockB 开始执行");
     while (true) {
      if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
        System.out.println(new Date().toString() + " LockB 锁住 obj2");
        if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
         System.out.println(new Date().toString() + " LockB 锁住 obj1");
         Thread.sleep(60 * 1000); // do something
        }else{
         System.out.println(new Date().toString() + "LockB 锁 obj1 失败");
        }
      }else{
        System.out.println(new Date().toString() + "LockB 锁 obj2 失败");
      }
      UnLockTest.a1.release(); // 释放
      UnLockTest.a2.release();
      Thread.sleep(10 * 1000); // 这里只是为了演示,所以tryAcquire只用1秒,而且B要给A让出能执行的时间,否则两个永远是死锁
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}

Die Ausgabestruktur des obigen Beispielcodes lautet:

Tue May 05 10:59:13 CST 2015 LockA 开始执行
Tue May 05 10:59:13 CST 2015 LockB 开始执行
Tue May 05 10:59:13 CST 2015 LockB 锁住 obj2
Tue May 05 10:59:13 CST 2015 LockA 锁住 obj1
Tue May 05 10:59:14 CST 2015LockB 锁 obj1 失败
Tue May 05 10:59:14 CST 2015LockA 锁 obj2 失败
Tue May 05 10:59:15 CST 2015 LockA 锁住 obj1
Tue May 05 10:59:15 CST 2015 LockA 锁住 obj2
【Verwandte Empfehlungen】


1.

Java-Video-Tutorial

2.

JAVA-Tutorial-Handbuch

3 .

Geek Academy Java-Video-Tutorial

Das obige ist der detaillierte Inhalt vonLösungen für Deadlocks, die bei der Java-Entwicklung auftreten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn