Поскольку мы продолжаем изучать моделирование и устранение проблем с производительностью в Kotlin, давайте обсудим, как заставить потоки переходить в состояние BLOCKED.
В этой последней статье серии о моделировании и устранении проблем с производительностью в Kotlin давайте обсудим, как перевести потоки в состояние BLOCKED. Поток войдет в BLOCKEDсостояние, если он не может получить блокировку объекта, потому что другой поток уже удерживает блокировку того же объекта и не освобождает ее.
Программа Kotlin BLOCKED Thread
Вот пример программы, которая переводит потоки в BLOCKEDсостояние.
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())
}
Пример программы содержит BlockedAppкласс. У этого класса есть start()метод. В этом методе 10создаются новые потоки. В AppThreadклассе есть run()метод, который вызывает getSomething()метод на AppObject. В этом getSomething()методе поток постоянно находится в спящем режиме; т. е. поток снова и снова спит в течение 10 минут. Но если вы заметили, getSomething()это синхронизированный метод. Синхронизированные методы могут выполняться только одним потоком за раз. Если какой-либо другой поток попытается выполнить getSomething()метод, в то время как предыдущий поток все еще работает над ним, то новый поток будет помещен в состояние BLOCKED.
В этом случае для выполнения метода запускается 10 потоков getSomething(). Однако только один поток получит блокировку и выполнит этот метод. Остальные 9 потоков будут переведены в BLOCKEDсостояние.
ПРИМЕЧАНИЕ. Если потоки находятся в BLOCKEDсостоянии в течение длительного времени, приложение может перестать отвечать на запросы.
Как диагностировать заблокированные темы
Вы можете диагностировать BLOCKEDпотоки вручную или автоматически.
Ручной подход
При ручном подходе в качестве первого шага необходимо захватить дампы потоков. Дамп потока показывает все потоки, находящиеся в памяти, и пути выполнения их кода. Вы можете захватить дамп потока, используя один из 8 вариантов, упомянутых здесь . Но важным критерием является то, что вам нужно захватить дамп потока прямо в момент возникновения проблемы (что может быть сложно сделать). После захвата дампа потока вам необходимо вручную импортировать дамп потока с рабочих серверов на локальный компьютер и проанализировать его с помощью инструментов анализа дампа потока, таких как fastThread или samurai .
Автоматизированный подход
С другой стороны, вы также можете использовать сценарий с открытым исходным кодом yCrash , который бы собирал 360-градусные данные (журнал GC, 3 снимка дампа потока, дамп кучи, netstat, iostat, vmstat, top, top -H и т. д.) сразу, как только проблема появляется в стеке приложений, и немедленно анализируйте их, чтобы создать отчет об анализе основных причин.
Мы использовали автоматизированный подход. Ниже приведен отчет об анализе основных причин, созданный инструментом yCrash, в котором указан источник проблемы.
yCrash выводит транзитивный граф зависимостей , показывающий, какие потоки получают BLOCKEDи кто их блокирует. На этом транзитивном графе вы можете видеть, что «Поток-0» блокирует 9 других потоков. Если вы нажмете на имена потоков на графике, вы увидите трассировку стека этого конкретного потока.
Вот снимок экрана, на котором показана трассировка стека 9 потоков, находящихся в состоянии, BLOCKEDа также указана трассировка стека, в которой они застряли. Из трассировки стека видно, что поток застрял в com.buggyapp.blockedapp.AppObject#getSomething()методе.
Имея эту информацию, можно легко определить основную причину BLOCKEDпотоков состояний.
видео
Чтобы увидеть визуальное прохождение этого поста, нажмите ниже:
#Открытый #Источник #Потоки #Состояния #Котлин #Язык #Программирования #Хаос #Инженерия