参考连接:https://www.androidperformance.com/2019/12/06/Android-Systrace-Binder/
monitor contention with owner Binder:1605_B (4667) at void
com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)
(ActivityTaskManagerService.java:1733) waiters=2 blocking from android.app.ActivityManager$StackInfo
com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)
上面的话分两段来看,以 blocking 为分界线
monitor contention with owner Binder:1605_B (4667) at void
com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)
(ActivityTaskManagerService.java:1733) waiters=2
Monitor 指的是当前锁对象的池,在 Java 中,每个对象都有两个池,锁(monitor)池和等待池:
锁池(同步队列 SynchronizedQueue ):假设线程 A 已经拥有了某个对象(注意:不是类 )的锁,而其它的线程想要调用这个对象的某个 synchronized 方法(或者 synchronized 块),由于这些线程在进入对象的 synchronized 方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程 A 拥有,所以这些线程就进入了该对象的锁池中。
这里用了争夺(contention)这个词,意思是这里由于在和目前对象的锁正被其他对象(Owner)所持有,所以没法得到该对象的锁的拥有权,所以进入该对象的锁池
Owner : 指的是当前拥有这个对象的锁的对象。这里是 Binder:1605_B,4667 是其线程 ID。
at 后面跟的是拥有这个对象的锁的对象正在做什么。这里是在执行 void com.android.server.wm.ActivityTaskManagerService.activityPaused 这个方法,其代码位置是 :ActivityTaskManagerService.java:1733 其对应的代码如下:
com/android/server/wm/ActivityTaskManagerService.java
@Override
public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) { // 1733 是这一行
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
}
可以看到这里 synchronized (mGlobalLock) ,获取了 mGlobalLock 锁的拥有权,在他释放这个对象的锁之前,任何其他的调用 synchronized (mGlobalLock) 的地方都得在锁池中等待
waiters 值得是锁池里面正在等待锁的操作的个数;这里 waiters=2 表示目前锁池里面已经有一个操作在等待这个对象的锁释放了,加上这个的话就是 3 个了
blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)
第二段信息相对来说简单一些,就是标识了当前被阻塞等锁的方法 , 这里是 ActivityManager 的 getFocusedStackInfo 被阻塞,其对应的代码
com/android/server/wm/ActivityTaskManagerService.java
@Override
public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) { // 2064 是这一行
ActivityStack focusedStack = getTopDisplayFocusedStack();
if (focusedStack != null) {
return mRootActivityContainer.getStackInfo(focusedStack.mStackId);
}
return null;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
可以看到这里也是调用了 synchronized (ActivityManagerService.this) ,从而需要等待获取 ams 对象的锁拥有权
上面这段话翻译过来就是ActivityTaskManagerService 的 getFocusedStackInfo 方法在执行过程中被阻塞,原因是因为执行同步方法块的时候,没有拿到同步对象的锁的拥有权;需要等待拥有同步对象的锁拥有权的另外一个方法ActivityTaskManagerService.activityPaused 执行完成后,才能拿到同步对象的锁的拥有权,然后继续执行
可以对照原文看上面的翻译
monitor contention with owner Binder:1605_B (4667)
at void com.android.server.wm.ActivityTaskManagerService.activityPaused(android.os.IBinder)(ActivityTaskManagerService.java:1733)
waiters=2
blocking from android.app.ActivityManager$StackInfo com.android.server.wm.ActivityTaskManagerService.getFocusedStackInfo()(ActivityTaskManagerService.java:2064)
还是上面那个 Systrace,Binder 信息里面显示 waiters=2,意味着前面还有两个操作在等锁释放,也就是说总共有三个操作都在等待 Binder:1605_B (4667) 释放锁,我们来看一下 Binder:1605_B 的执行情况
从上图可以看到,Binder:1605_B 正在执行 activityPaused,中间也有一些其他的 Binder 操作,最终 activityPaused 执行完成后,释放锁
下面我们就把这个逻辑里面的执行顺序理顺,包括两个 waiters
上图中可以看到 mGlobalLock 这个对象锁的争夺情况
上图可以看到 mGlobalLock 锁的释放和后续的流程
经过上面 6 步,这一轮由于 mGlobalLock 对象锁引起的等锁现象结束。这里只是一个简单的例子,在实际情况下,SystemServer 中的 BInder 等锁情况会非常严重,经常 waiter 会到达 7 - 10 个,非常恐怖,比如下面这种: