1. 啥是死锁
好比有两个线程,T1和T2,有两把锁L1和L2。目前程序运行状态是这样的,T1拿了锁L1,T2拿了锁L2,而且T1企图再拿第二把锁L2,T2则企图拿第一把锁L1。但是他们各自都没有把已有的锁释放,于是便各自进入阻塞等待。你等我释放,我等你释放,我俩谁都不先放,这样就陷入僵持,造成死锁。
2. 看个死锁的例子
该例子引用于:https://blog.csdn.net/ch853199769/article/details/88528748
"ActivityManager" prio=5 tid=12 Blocked
...
at ActivityManagerService.updateCpuStatsNow(ActivityManagerService.java:3107)
- waiting to lock <0x0037ca7c> (aandroid.util.SparseArray) held by thread 135
- locked <0x0dfe4378> (a com.android.internal.os.ProcessCpuTracker)
- locked <0x064e7a29> (a com.android.internal.os.BatteryStatsImpl)
at AppErrors.appNotResponding(AppErrors.java:983)
at ActivityManagerService$17.run(ActivityManagerService.java:13416)
at android.os.Handler.handleCallback(Handler.java:793)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:173)
at android.os.HandlerThread.run(HandlerThread.java:65)
at com.android.server.ServiceThread.run(ServiceThread.java:46)
"Binder:1328_15" prio=5 tid=135 Blocked
...
at BatteryStatsService.noteEvent(BatteryStatsService.java:422)
- waiting to lock <0x064e7a29> (acom.android.internal.os.BatteryStatsImpl) held by thread 12
at ActivityManagerService.updateProcessForegroundLocked(ActivityManagerService.java:23108)
at ActivityManagerService.importanceTokenDied(ActivityManagerService.java:8177)
- locked <0x0ef100c6> (a ActivityManagerService)
- locked <0x0037ca7c> (a android.util.SparseArray)
at ActivityManagerService$13.binderDied(ActivityManagerService.java:8209)
at android.os.BinderProxy.sendDeathNotice(Binder.java:842)
————————————————
版权声明:本文为CSDN博主「安德路」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ch853199769/article/details/88528748
先解释一下trace的含义,有些在本例中并未出现,也一起介绍
- prio: 代表线程优先级
- tid: java线程id
- Blocked:线程阻塞,指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。
- waiting to lock <0x00000000a2b4f3a>: 线程在等待给这个 0x00000000a2b4f3a 地址上锁
- Deadlock:死锁,多个线程调用间,进入相互资源占用,导致一直等待无法释放
- Runnable:线程正在执行中,该线程占用资源,正在进行某种操作
- waiting for monitor entry”说明此线程通过 synchronized(obj) {……} 申请进入了临界区,从而进入了下图1中的“Entry Set”队列,但该 obj 对应的 monitor 被其他线程拥有,所以本线程在 Entry Set 队列中等待
- Waiting on condition:等待资源,或等待某个条件的发生。具体原因需结合 stacktrace来分析。(1) 如果堆栈信息明确是应用代码,则证明该线程正在等待资源。一般是大量读取某资源,且该资源采用了资源锁的情况下,线程进入等待状态,等待资源的读取。又或者,正在等待其他线程的执行等。(2) 如果发现有大量的线程都在处在 Wait on condition,从线程 stack看,正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。(3) 另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。
- TIMED_WAITING (parking):指等待状态,但这里指定了时间,到达指定的时间后自动退出等待状态;parking指线程处于挂起中。
- 以上内容引用于https://www.cnblogs.com/kabi/p/5073706.html
本例中,两个线程ActivityManager和Binder,线程ActivityManager处于Blocked,waiting to lock <0x0037ca7c> (aandroid.util.SparseArray) held by thread 135,从这句来看是等待上锁,但该锁被thread 135占有。再看线程Binder,同样的问题,waiting to lock <0x064e7a29> (acom.android.internal.os.BatteryStatsImpl) held by thread 12,等待thread 12释放锁,也就是线程ActivityManager。显然,这就是死锁了。
网友评论