Dans ce dernier article de la série sur la simulation et le dépannage des problèmes de performances dans Kotlin, expliquons comment faire entrer les threads dans un BLOCKED
État. Un fil entrera dans un BLOCKED
indique s’il ne peut pas acquérir un verrou sur un objet car un autre thread détient déjà le verrou sur le même objet et ne le libère pas.
Programme de threads BLOQUÉS par Kotlin
Voici un exemple de programme qui ferait passer les threads dans un BLOCKED
État.
package com.buggyapp
class BlockedApp {
fun start() {
println("BlockedApp:started")
for (counter in 0..9) { // Launch 10 threads.
AppThread().start()
}
}
}
class AppThread : Thread() {
override fun run() {
AppObject.something
}
}
object AppObject {
@get:Synchronized
val something: Unit
get() {
while (true) {
try {
Thread.sleep(6000000.toLong())
} catch (e: Exception) {
}
}
}
}
fun main() {
println(BlockedApp().start())
}
L’exemple de programme contient les BlockedApp
classe. Cette classe a un start()
méthode. Dans cette méthode, 10
de nouveaux fils sont créés. Dans le AppThread
classe il y a une run()
méthode qui invoque la getSomething()
méthode sur la AppObject
. Dans ce getSomething()
méthode, le thread est mis en veille continue ; c’est-à-dire que le thread dort à plusieurs reprises pendant 10 minutes encore et encore. Mais si vous remarquez, le getSomething()
est une méthode synchronisée. Les méthodes synchronisées ne peuvent être exécutées que par un seul thread à la fois. Si un autre thread essaie d’exécuter le getSomething()
alors que le thread précédent travaille toujours dessus, le nouveau thread sera placé dans la BLOCKED
État.
Dans ce cas, 10 threads sont lancés pour exécuter le getSomething()
méthode. Cependant, un seul thread acquerra un verrou et exécutera cette méthode. Les 9 fils restants seront mis dans un BLOCKED
État.
NOTE: Si les threads sont dans BLOCKED
pendant une période prolongée, l’application peut ne plus répondre.
Comment diagnostiquer les threads BLOQUÉS
Vous pouvez diagnostiquer BLOCKED
threads soit par une approche manuelle ou automatisée.
Approche manuelle
Dans l’approche manuelle, vous devez capturer les thread dumps comme première étape. Un vidage de thread affiche tous les threads qui sont en mémoire et leur chemin d’exécution de code. Vous pouvez capturer un thread dump en utilisant l’une des 8 options mentionnées ici. Mais un critère important est le suivant : vous devez capturer le vidage du thread juste au moment où le problème se produit (ce qui peut être difficile à faire). Une fois le vidage de thread capturé, vous devez importer manuellement le vidage de thread de vos serveurs de production vers votre ordinateur local et l’analyser à l’aide d’outils d’analyse de vidage de thread tels que fastThread ou samurai.
Approche automatisée
D’autre part, vous pouvez également utiliser le script open source yCrash, qui capturerait des données à 360 degrés (journal GC, 3 instantanés de thread dump, heap dump, netstat, iostat, vmstat, top, top -H, etc.) dès que le problème apparaît dans la pile d’applications et analysez-les instantanément pour générer un rapport d’analyse des causes profondes.
Nous avons utilisé l’approche automatisée. Vous trouverez ci-dessous le rapport d’analyse des causes profondes généré par l’outil yCrash mettant en évidence la source du problème.
yCrash signale un graphique de dépendance transitif de 9 threads BLOQUÉS
yCrash imprime un graphique de dépendance transitif qui montre quels threads obtiennent BLOCKED
et qui les bloque. Dans ce graphe transitif, vous pouvez voir « Thread-0 » bloquer 9 autres threads. Si vous cliquez sur les noms de threads dans le graphique, vous pouvez voir la trace de pile de ce thread particulier.
yCrash signale la trace de la pile de 9 threads qui sont dans l’état BLOQUÉ
Voici la capture d’écran qui montre la trace de la pile des 9 threads qui sont dans le BLOCKED
state et il indique également la trace de la pile dans laquelle ils sont bloqués. À partir de la trace de la pile, vous pouvez observer que le thread est bloqué sur le com.buggyapp.blockedapp.AppObject#getSomething()
méthode.
Munis de ces informations, on peut facilement identifier la cause profonde du BLOCKED
fils d’état.
Vidéo
Pour voir la présentation visuelle de cet article, cliquez ci-dessous :