堆栈日志分析,总结如下
jstack的日志,我们到底如何查看呢?
线程的状态有:
new、Runnable、running、waiting、timed_waiting、blocked、dead
线程状态变迁图
各状态说明:
New: 当线程对象创建时存在的状态,此时线程不可能执行。
Runnable:当调用thread.start()后,线程变成Runnable状态。只要得到CPU,就可以执行。
Running: 线程正在运行,就绪状态的线程获取了CPU,执行程序代码
Waiting: 执行Thread.join()或在锁对象调用obj.wait()等情况就会进入该状态,表明线程正处于等待某个资源或条件发生时来唤醒自己。
Timed_Waiting: 执行Thread.sleep(long), thread.join(long) 或obj.wait(long) 等就会进入该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
Blocked: 如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态;
Dead: 线程执行完毕,或者跑出了未捕获的异常之后,会进入Dead状态,表示该线程结束,
其次,对于jstack日志,我们要着重关注如下关键信息
Deadlock:表示有死锁
Waiting on condition:等待某个资源或条件来唤醒自己。具体需要结合jstacktrace来分析,具体原因需结合stackstrace来分析。
Blocked: 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
Waiting on monitor entry: 在等待获取锁
in Object.wait(): 获取锁之后又执行obj.wait()放弃锁
对于 Waiting on monitor entry 和 in Object.wait()的详情描述:Monitor 是Java中用以实现线程之间的互斥与协作的主要手段,太刻意看成是对象或class的锁。每一个对象都有,也仅有一个monitor. 每个monitor 在某个时刻,只能被一个线程拥有,该线程就是“Active Thread”,而其他线程都是“Waiting Thread”, 分别在两个队列“Entry Set” 和 “Wait Set”在里边等候。 在Entry Set中等待的线程状态时“Waiting for monitor entry”,而在“Wait” Set”中等待的线程状态时“in Object.wait()”
程序先输出main, 在输出thread, 说明main的线程是先获得同步锁的
执行jstack pid 输出信息如下:
可以看到thread1在进行等待获取到锁,此时进入waiting for monitor entry ,并是阻塞状态。
而main线程提前获取到锁,当由于调用了sleep此时进入到Timed_waiting状态,此时main线程锁住的对象地址是0x000000076bf4ef60,而thread1正在等待获取这个锁对象。
中间介绍几个参数指标
prio: 线程的优先级
tid: 线程id
nid: 操作系统映射的线程id,非常关键
0x000000002046f000 0x00000000029bf000 表示线程栈的起始地址。
从jstack日志中,可以看到:主线程获取到thread1对象上的锁,因为正在执行sleep操作,状态为TIMEE_WAITING,而thread1由于未获取到thread1对象上的锁,因为处于Blocked状态。
再细看,thread1 正在“waiting to lock <0x000000076bf4ef60>”,即试图在地址为<0x000000076bf4ef60>所在的对象上获取锁,而该锁确被main线程占有(locked <0x000000076bf4ef60>).
main线程正在“waiting on condition”,说明正在等待某个条件触发,由jstackstrace来看,此线程正在sleep.
总结:
如果在jstack日志发现大量的线程在waiting to lock某个地址,只要能查到哪个线程获取到锁就可以方便定位到问题了。
执行后,查看jstack的日志如下
可以看到由于调用了object.wait()方法的时候放弃了锁,所以在thread2这个线程就出现了object.wait()状态,线程的状态就是waiting,等待notify来进行唤醒。
由于main线程在获取thread2的线程锁之后,调用了sleep方法,所以此时进入了waiting on condition等待某一个资源,进入到time_waiting状态。
来,一块看下执行结果,此时main线程进入了main on condition 状态,等待某一个资源,此时可以看到是在a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject 进行了等待,阻塞住了,这是由于put发生了阻塞。
对于jstack日志,我们要着重关注如下关键信息
Deadlock: 表示有死锁。
Waiting on condition : 等待某个资源或条件发生时 来唤醒自己。 具体需要结果jstackspace 来分析,比如线程正在sleep,网络读写繁忙而等待
Blocked: 阻塞
Waiting on monitor entry: 在等待获取锁
如果说系统慢,那么就要特别关注 Blocked, Waiting on condition
如果说系统CPU耗的高,那么肯定是线程执行有无限循环,那么此时要关注系下Runnable状态。
谢谢大家,小小总结,望大家喜欢和关注~
页面更新:2024-04-27
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号