Maison  >  Article  >  Java  >  Solutions aux blocages rencontrés dans le développement Java

Solutions aux blocages rencontrés dans le développement Java

Y2J
Y2Joriginal
2017-05-05 14:56:111290parcourir

Cet article présente principalement l'explication détaillée et des exemples simples du blocage multithread Java. Les amis qui en ont besoin peuvent s'y référer

Le blocage est une situation dans laquelle plusieurs threads sont bloqués en même temps. tous attendent qu’une ressource soit libérée. Le thread étant bloqué indéfiniment, le programme ne peut pas se terminer correctement.

Quatre conditions nécessaires à l'impasse Java :

1> Utilisation mutuellement exclusive, c'est-à-dire lorsqu'une ressource est utilisée (occupée) par un thread, un autre Le fil ne peut pas utiliser

2> et n'est pas préemptif. Le demandeur de ressource ne peut pas saisir de force la ressource du propriétaire de la ressource, et la ressource ne peut être libérée activement que par le propriétaire de la ressource.

3> Demander et maintenir, c'est-à-dire lorsque le demandeur de ressources demande d'autres ressources tout en maintenant les camarades dans les ressources d'origine.

4> Boucle en attente, c'est-à-dire qu'il y a une file d'attente d'attente : P1 occupe les ressources de P2, P2 occupe les ressources de P3, et P3 occupe les ressources de P1. Cela crée une boucle d'attente.

Lorsque les quatre conditions ci-dessus sont remplies, une impasse se forme. Bien entendu, en cas de blocage, si l’une des conditions ci-dessus n’est pas respectée, le blocage disparaîtra. Utilisons du code Java pour simuler l'apparition d'un blocage.

Les moyens de résoudre le problème de blocage sont les suivants : l'un consiste à utiliser la synchronisation et l'autre consiste à utiliser l'implémentation du verrouillage explicite Lock.

Et si le verrou est mal utilisé et que plusieurs objets doivent être verrouillés en même temps, une situation de blocage se produira, comme suit :

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

Le résultat de l'exécution du code ci-dessus est :

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

À ce moment, un blocage se produit.

Afin de résoudre ce problème, nous n'utilisons pas de déverrouillage explicite, nous utilisons des sémaphores pour le contrôler.

Le sémaphore peut contrôler le nombre de threads pouvant accéder à la ressource. Nous précisons ici qu'il n'est accessible que par un seul thread, ce qui est similaire au verrouillage. Le sémaphore peut spécifier le délai d'attente pour l'acquisition, et nous pouvons effectuer un traitement supplémentaire en fonction de ce délai d'attente.

Si vous ne parvenez pas à l'obtenir, vous pouvez généralement réessayer, ou spécifier le nombre de tentatives, ou vous pouvez sortir immédiatement.

Regardez le code suivant :

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

La structure de sortie de l'exemple de code ci-dessus est :

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

【Recommandations associées】

1 Tutoriel vidéo Java

2. Manuel du didacticiel JAVA

3 . Tutoriel vidéo Java de la Geek Academy

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn