外观
同步屏障为什么能让绘制相关消息先执行?
标准回答
同步屏障是 MessageQueue 中影响消息选择的机制。取消息遇到生效的屏障时,后面的普通同步消息暂时不能越过它,而符合条件的异步消息可以继续被取出。这里的“异步”是消息属性,不表示放到后台线程执行。
ViewRootImpl 安排遍历时,框架会配合屏障与 Choreographer 的帧消息,让相关帧工作不被屏障之后的普通同步消息持续推迟;进入对应遍历处理时再移除屏障。业务通常不需要、也不应该直接管理这些隐藏机制。
屏障只影响下一条取什么消息。主线程如果已经进入一个耗时 200ms 的方法,它不会让绘制代码突然抢占这个方法。所以有屏障、有异步帧消息,仍然可能因为主线程长任务而卡顿。
异步 Handler 可以使其消息不受同步屏障约束,但仍在它绑定的 Looper 上执行。把重活改成异步消息,只是可能改变排队顺序,不是解决主线程耗时的办法。
关键机制
- 同步 / 异步消息属性与同步 / 异步 IPC 不是同一个概念,也不等同于是否新建线程。
- 屏障需要按框架约定移除;遗漏可能导致普通消息长期得不到处理。
- 不同 Android 版本的队列实现细节可能变化,理解调度语义即可,不把某版内部结构当作公共 API。
通俗例子
队列有一个已生效屏障,后面的普通消息等待,而到期的异步帧消息可以被处理;但当前正在执行的磁盘读取,仍要先结束或返回。
追问与回答
IdleHandler 和同步屏障有关吗?
它们都涉及 MessageQueue,但作用不同。IdleHandler 是队列满足空闲条件时执行回调;屏障是改变哪些消息能被取出的限制。不能把 IdleHandler 理解成一条能越过屏障的异步消息,也不能把有屏障导致的等待直接当成业务可以可靠执行空闲任务的时机。
易混淆点
“屏障提高优先级”只是简化说法;它不是操作系统线程优先级,也不能打断当前调用。
参考资料
内容来源
- Android 技术札记 · 原条目
sync-barrier