不会阻塞之前的同步消息
如果插入的同步屏障,在中间位置,只有在同步屏障之前的消息执行完之后,同步屏障才会起作用.
同步屏障(Sync Barrier)只有在它之前的同步消息执行完之后,才会开始生效。
我们可以从 MessageQueue 中插入同步屏障的逻辑来看其实际行为:
插入同步屏障逻辑(核心代码)
Message prev = null;
Message p = mMessages;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
// 将同步屏障插入在 prev 和 p 之间
if (prev != null) {
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
这个逻辑说明:
• 插入的同步屏障会按时间顺序插入到队列中,通常是在一个合适的 when 时间点之后;
• 并不会把它放在消息队列的头部,而是会根据 when 找到它应有的位置。
所以:同步屏障的生效逻辑是这样的:
• MessageQueue 在查找下一个可执行的消息时,如果遇到了同步屏障,会:
• 跳过所有同步消息(target != null);
• 继续查找后面的异步消息(target == null);
• 如果找不到异步消息,就停止 dispatchMessage,从而让主线程“空转”并阻塞;
• 直到某个异步消息或者屏障被移除,主线程才恢复执行。
举个例子:
假设消息队列如下:
[同步A] → [同步B] → [屏障] → [同步C] → [异步D]
• 在屏障被插入到 B 和 C 之间的情况下,
• MessageQueue 处理完 A 和 B 后,到达“屏障”,开始只处理“异步”消息;
• 所以,C 会被屏蔽,D 会被执行;
• 如果 A 和 B 还没有执行完,屏障其实还未起作用。
结论:
只有在消息队列中,屏障之前的同步消息执行完后,屏障才会成为“当前首个待处理消息”,它才开始起作用。