Skip to content

Commit 29eefd1

Browse files
author
Tan Minghui
committed
Update articles
1 parent b8efb87 commit 29eefd1

File tree

1 file changed

+76
-1
lines changed

1 file changed

+76
-1
lines changed

android/Android 线程间通信.md

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
## 种类
44

55
- 单向管道。非 Android 独有
6-
- 共享内通信
6+
- 共享内存通信
77
- 消费者生产者模型 — BlockingQueue。非 Android 独有
88
- 消息队列。Handler 机制
9+
- LocalSocket
910

1011

1112

@@ -19,6 +20,80 @@
1920

2021

2122

23+
### 同步屏障机制
24+
25+
同步屏障可以通过MessageQueue.postSyncBarrier函数来设置:
26+
27+
```java
28+
private int postSyncBarrier(long when) {
29+
// Enqueue a new sync barrier token.
30+
// We don't need to wake the queue because the purpose of a barrier is to stall it.
31+
synchronized (this) {
32+
final int token = mNextBarrierToken++;
33+
final Message msg = Message.obtain();
34+
msg.markInUse();
35+
msg.when = when;
36+
msg.arg1 = token;
37+
Message prev = null;
38+
Message p = mMessages;
39+
if (when != 0) {
40+
while (p != null && p.when <= when) {
41+
prev = p;
42+
p = p.next;
43+
}
44+
}
45+
if (prev != null) { // invariant: p == prev.next
46+
msg.next = p;
47+
prev.next = msg;
48+
} else {
49+
msg.next = p;
50+
mMessages = msg;
51+
}
52+
return token;
53+
}
54+
}
55+
```
56+
可以看到,该函数仅仅是创建了一个Message对象并加入到了消息链表中。乍一看好像没什么特别的,但是这里面有一个很大的不同点是该**Message没有target**
57+
58+
我们通常都是通过Handler发送消息的,Handler中发送消息的函数有post***、sendEmptyMessage***以及sendMessage***等函数,而这些函数最终都会调用enqueueMessage函数:
59+
60+
```java
61+
//Handler.java
62+
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
63+
msg.target = this;
64+
//...
65+
return queue.enqueueMessage(msg, uptimeMillis);
66+
}
67+
```
68+
69+
可以看到enqueueMessage为msg设置了target字段。所以,从代码层面上来讲,**同步屏障就是一个Message,一个target字段为空的Message**
70+
71+
当设置了同步屏障之后,**next函数将会忽略所有的同步消息**,返回异步消息。设置了同步屏障之后,Handler只会处理异步消息。再换句话说,同步屏障为Handler消息机制增加了一种简单的优先级机制,异步消息的优先级要高于同步消息。
72+
73+
#### 应用
74+
75+
Android应用框架中为了更快的响应UI刷新事件在ViewRootImpl.scheduleTraversals中使用了同步屏障
76+
77+
```java
78+
void scheduleTraversals() {
79+
if (!mTraversalScheduled) {
80+
mTraversalScheduled = true;
81+
//设置同步障碍,确保mTraversalRunnable优先被执行
82+
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
83+
//内部通过Handler发送了一个异步消息
84+
mChoreographer.postCallback(
85+
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
86+
if (!mUnbufferedInputDispatch) {
87+
scheduleConsumeBatchedInput();
88+
}
89+
notifyRendererOfFramePending();
90+
pokeDrawLockIfNeeded();
91+
}
92+
}
93+
```
94+
95+
96+
mTraversalRunnable调用了performTraversals执行measure、layout、draw。为了让mTraversalRunnable尽快被执行,在发消息之前调用MessageQueue.postSyncBarrier设置了同步屏障。
2297

2398

2499
## 总结

0 commit comments

Comments
 (0)