63 votes

Détection des blocages en Java

Il y a longtemps, j'ai sauvegardé une phrase d'un livre de référence sur Java : "Java n'a pas de mécanisme pour gérer le deadlock. Il ne saura même pas qu'un deadlock s'est produit." (Head First Java 2ème édition, p.516)

Alors, qu'en est-il ? Y a-t-il un moyen d'attraper un cas de deadlock en Java ? Je veux dire, y a-t-il un moyen pour que notre code comprenne qu'un cas de deadlock s'est produit ?

1 votes

Java est-il différent des autres langages à cet égard ?

1 votes

Il n'est pas impossible de détecter une impasse - c'est juste assez difficile

1 votes

Par exemple, la plupart des bases de données détectent les blocages.

81voto

staffan Points 3299

Depuis le JDK 1.5, il existe des méthodes très utiles dans le module java.lang.management pour trouver et inspecter les blocages qui se produisent. Voir le findMonitorDeadlockedThreads() y findDeadlockedThreads() de la méthode ThreadMXBean classe.

Une façon possible d'utiliser ceci est d'avoir un thread de chien de garde séparé (ou une tâche périodique) qui fait ceci.

Exemple de code :

  ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
  long[] ids = tmx.findDeadlockedThreads();
  if (ids != null) {
     ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
     System.out.println("The following threads are deadlocked:");
     for (ThreadInfo ti : infos) {
        System.out.println(ti);
     }
  }

1 votes

C'est génial que Java ait ça ! Je pense que j'étais sur le point de m'effondrer et de commencer à pleurer.

18voto

Steve K Points 10475

JConsole est capable de détecter les blocages dans une application en cours d'exécution.

11voto

Alex Miller Points 28225

Les JDK 5 et 6 fournissent des informations sur les verrous détenus dans un vidage complet des threads (obtenu avec kill -3, jstack, jconsole, etc.). Le JDK 6 contient même des informations sur ReentrantLock et ReentrantReadWriteLock. Il est possible, à partir de ces informations, de diagnostiquer un deadlock en trouvant un cycle de verrouillage : Le thread A détient le verrou 1, le thread B détient le verrou 2, et soit A demande le verrou 2, soit B demande le verrou 1. D'après mon expérience, c'est généralement assez évident.

D'autres outils d'analyse peuvent en fait trouver des blocages potentiels même s'ils ne se produisent pas. Les outils de threads de vendeurs comme OptimizeIt, JProbe, Coverity, etc. sont de bons endroits où regarder.

9voto

Dave Griffiths Points 688

Notez qu'il existe un type d'impasse utilisant le paquet concurrent qui est très difficile à déboguer. C'est le cas lorsque vous avez un ReentrantReadWriteLock et qu'un thread s'empare du verrou de lecture puis (disons) essaie d'entrer dans un moniteur détenu par un autre thread qui attend également de s'emparer du verrou d'écriture. Ce qui rend le débogage particulièrement difficile, c'est qu'il n'y a pas d'enregistrement de la personne qui a accédé à un verrou de lecture. Il s'agit simplement d'un compte. Le thread peut même avoir lancé une exception et mourir en laissant le compte de lecture non nul.

Voici un exemple d'impasse que la méthode findDeadlockedThreads mentionnée plus haut ne parvient pas à détecter :

import java.util.concurrent.locks.*;
import java.lang.management.*;

public class LockTest {

    static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args) throws Exception {
        Reader reader = new Reader();
        Writer writer = new Writer();
        sleep(10);
        System.out.println("finding deadlocked threads");
        ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
        long[] ids = tmx.findDeadlockedThreads();
        if (ids != null) {
            ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
            System.out.println("the following threads are deadlocked:");
            for (ThreadInfo ti : infos) {
                System.out.println(ti);
            }
        }
        System.out.println("finished finding deadlocked threads");
    }

    static void sleep(int seconds) {
        try {
            Thread.currentThread().sleep(seconds*1000);
        } catch (InterruptedException e) {}
    }

    static class Reader implements Runnable {
        Reader() {
            new Thread(this).start();
        }
        public void run() {
            sleep(2);
            System.out.println("reader thread getting lock");
            lock.readLock().lock();
            System.out.println("reader thread got lock");
            synchronized (lock) {
                System.out.println("reader thread inside monitor!");
                lock.readLock().unlock();
            }
        }
    }

    static class Writer implements Runnable {
        Writer() {
            new Thread(this).start();
        }
        public void run() {
            synchronized (lock) {
                sleep(4);
                System.out.println("writer thread getting lock");
                lock.writeLock().lock();
                System.out.println("writer thread got lock!");
            }
        }
    }
}

0 votes

Très bon exemple... En dehors de la recherche de threads dans un état WAITING/BLOCKED via jstack, y a-t-il d'autres indications que nous pourrions rechercher dans cette situation ?

6voto

luke Points 6688

En général, Java ne permet pas de détecter les blocages. Le mot-clé synchronisé et les moniteurs intégrés rendent le raisonnement sur les blocages un peu plus difficile que dans les langages avec verrouillage explicite.

Je vous suggère de migrer vers l'utilisation des verrous java.util.concurrent.Lock et autres afin de rendre vos schémas de verrouillage plus faciles à comprendre. En fait, vous pouvez facilement créer votre propre implémentation de l'interface de verrouillage avec détection des blocages. L'algorithme consiste essentiellement à parcourir le graphe de dépendance des verrous et à rechercher un cycle.

3 votes

Les verrous de java.util.concurrent.Lock intègrent la détection des blocages à partir du JDK 1.6. Voir java.lang.management.ThreadMXBean.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X