死锁分析
所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。对于锁更好的理解,先要理解monitor这个概念!
monitor直译过来是监视器的意思,专业一点叫管程。monitor是属于编程语言级别的,它的出现是为了解决操作系统级别关于线程同步原语的使用复杂性,类似于语法糖,对复杂操作进行封装。而java则基于monitor机制实现了它自己的线程同步机制,就是synchronized内置锁。monitor的作用就是限制同一时刻,只有一个线程能进入monitor框定的临界区,达到线程互斥,保护临界区中临界资源的安全,这称为线程同步使得程序线程安全。同时作为同步工具,它也提供了管理进程,线程状态的机制,比如monitor能管理因为线程竞争未能第一时间进入临界区的其他线程,并提供适时唤醒的功能。下图介绍了monitor的原理
进入区(Entry Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则成为拥有者;否则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
拥有者(The Owner):表示某一线程成功竞争到对象锁。
等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。
在分析dump日志时,经常会看到下面几种情况:
locked <地址> 目标:通过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操作。对象锁是可以线程重入的。
waiting to lock <地址> 目标:通过synchronized关键字,没有获取到了对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked。
waiting on <地址> 目标:通过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进入对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING。
parking to wait for <地址> 目标:park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包会出现的新的机制,与synchronized体系不同。
线程状态的产生原因分析如下:
Runnable:状态一般为RUNNABLE,The thread is either running or ready to run when it gets its CPU turn。
in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
waiting for monitor entry:进入区等待,状态为BLOCKED。
waiting on condition:等待区等待。该状态出现在线程等待某个条件的发生或者sleep。具体是什么原因,可以结合 stacktrace来分析。最常见的情况是线程在等待网络的读写,比如当网络数据没有准备好读时,线程处于这种等待状态,而一旦有数据准备好读之后,线程会重新激活,读取并处理数据。在Java引入 New IO之前,对于每个网络连接,都有一个对应的线程来处理网络的读写操作,即使没有可读写的数据,线程仍然阻塞在读写操作上,这样有可能造成资源浪费,而且给操作系统的线程调度也带来压力。在 New IO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。如果发现有大量的线程都处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如 netstat统计单位时间的发送包的数目,看是否很明显超过了所在网络带宽的限制;观察CPU的利用率,看系统态的CPU时间是否明显大于用户态的 CPU时间;另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了,将被唤醒。
sleeping:休眠的线程,调用了Thread.sleep()。
锁竞争分析
如果一个线程尝试进入另一个线程正在执行的同步块或者方法时,便会出现锁竞争。第二个线程就必须等待前一个线程执行完这个同步块并释放掉监视器(monitor)。
如果大量线程在“waiting for monitor entry”: 则可能是一个全局锁阻塞住了大量线程。
排查方法
我们可以方便的通过命令jstack -l pid 排查死锁和锁竞争。更多关于jvm调优的命令可以参考文章:文章来源:https://www.toymoban.com/news/detail-730017.html
Java体系性能测试进阶必须了解的知识点——Thread Dump-CSDN博客文章来源地址https://www.toymoban.com/news/detail-730017.html
到了这里,关于Java体系性能测试进阶必须了解的知识点——死锁分析和锁竞争分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!