当前位置:首页>安卓APP>安卓17版本上google引入了无锁消息队?老版本MessageQueue的锁解密剖析

安卓17版本上google引入了无锁消息队?老版本MessageQueue的锁解密剖析

  • 2026-11-07 16:45:48
安卓17版本上google引入了无锁消息队?老版本MessageQueue的锁解密剖析

背景:

这两天学员朋友们在vip群都在讨论google官方发布的blog:安卓17版本上google引入了无锁消息队,提升手机流畅度的文章。

原文地址(可能国内无法访问):

https://android-developers.googleblog.com/2026/02/under-hood-android-17s-lock-free.html

谷歌在2026年宣布,安卓17系统将通过引入DeliQueue系统显著提升手机的流畅度,减少用户在日常操作中遇到的卡顿和滑动不流畅问题。新系统的核心改进在于优化了MessageQueue的内存锁定机制,从而缩短了软件线程之间的等待时间。 

原来MessageQueue锁的核心痛点:

底层原理:Android17 的无锁消息队 

Under the hood: Android 17's lock-free MessageQueue

学员提出疑问:

请问具体MessageQueue中的锁具体在哪里体现的呢?马哥方便贴出一下相关的源码么,只是看到文章写的MessageQueue有锁竞争,但是没注意看哪里有锁,还有MessageQueue应该也还有native代码吧,也有锁么?

下面来带大家剖析一下MessageQueue的相关锁到底在哪里,对相关源码进行剖析。

MessageQueue的java部分锁lock展示:

正常java端进行发送消息,都是只需要有一个Handler调用sendMessage方法就可以,不管任何线程都可以调用Handler的sendMessage方法进行消息发送。

frameworks/base/core/java/android/os/Handler.java

/**     * Pushes a message onto the end of the message queue after all pending messages     * before the current time. It will be received in {@link #handleMessage},     * in the thread attached to this handler.     *       * @return Returns true if the message was successfully placed in to the      *         message queue.  Returns false on failure, usually because the     *         looper processing the message queue is exiting.     */publicfinal boolean sendMessage(@NonNull Message msg){return sendMessageDelayed(msg, 0);    }

注意:post消息其实也是最后调用到了sendMessage相关方法

/**     * Causes the Runnable r to be added to the message queue.     * The runnable will be run on the thread to which this handler is      * attached.      *       * @param r The Runnable that will be executed.     *      * @return Returns true if the Runnable was successfully placed in to the      *         message queue.  Returns false on failure, usually because the     *         looper processing the message queue is exiting.     */publicfinal boolean post(@NonNull Runnable r){return  sendMessageDelayed(getPostMessage(r), 0);    }

这里会调用到sendMessageDelayed

publicfinal boolean sendMessageDelayed(@NonNull Message msg, long delayMillis){if (delayMillis < 0) {            delayMillis = 0;        }return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }

这里又会调用到sendMessageAtTime方法

public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis){        MessageQueue queue = mQueue;return enqueueMessage(queue, msg, uptimeMillis);//调用到enqueueMessage    }

再看看enqueueMessage方法

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis){        msg.target = this;        msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {            msg.setAsynchronous(true);        }returnqueue.enqueueMessage(msg, uptimeMillis);//这里最后调用到MessageQueue的enqueueMessage方法    }

再看看MessageQueue的enqueueMessage方法:

frameworks/base/core/java/android/os/MessageQueue.java

boolean enqueueMessage(Message msg, long when){if (msg.target == null) {thrownew IllegalArgumentException("Message must have a target.");        }        synchronized (this) {//这里是锁            msg.markInUse();            msg.when = when;            Message p = mMessages;            boolean needWake;if (p == null || when == 0 || when < p.when) {// New head, wake up the event queue if blocked.                msg.next = p;                mMessages = msg;                needWake = mBlocked;            } else {// Inserted within the middle of the queue.  Usually we don't have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.                needWake = mBlocked && p.target == null && msg.isAsynchronous();                Message prev;for (;;) {                    prev = p;                    p = p.next;if (p == null || when < p.when) {break;                    }if (needWake && p.isAsynchronous()) {                        needWake = false;                    }                }                msg.next = p; // invariant: p == prev.next                prev.next = msg;            }// We can assume mPtr != 0 because mQuitting is false.if (needWake) {                nativeWake(mPtr);            }        }returntrue;    }

MessageQueue的native部分锁lock展示:

看看native层面如何发送Message可以看到主要调用是sendMessage方法 system/core/libutils/Looper.cpp

voidLooper::sendMessage(const sp<MessageHandler>& handler, const Message& message){nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);    sendMessageAtTime(now, handler, message);}

在看看sendMessageAtTime方法

voidLooper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,const Message& message){size_t i = 0;    { // acquire lock        AutoMutex _l(mLock);//这里也有一个锁保护size_t messageCount = mMessageEnvelopes.size();while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {            i += 1;        }MessageEnvelope messageEnvelope(uptime, handler, message);        mMessageEnvelopes.insertAt(messageEnvelope, i, 1);// Optimization: If the Looper is currently sending a message, then we can skip// the call to wake() because the next thing the Looper will do after processing// messages is to decide when the next wakeup time should be.  In fact, it does// not even matter whether this code is running on the Looper thread.if (mSendingMessage) {return;        }    } // release lock// Wake the poll loop only when we enqueue a new message at the head.if (i == 0) {        wake();    }}

可以看到在 Looper::sendMessageAtTime方法中对mMessageEnvelopes进行操作时候都是有lock进行保护的。

更多vip免费系统开发经典大厂面试题库获取,课程优惠购买成为vip学员进入vip群,积极讨论各种行业难点痛点疑难问题,答疑服务等。

请联系马哥微信:

目前所有专题课程如下:
1、经典fw的入门到精通实战八件套专题
详细课表:
Android Framework开发rom实战合集课表/车载车机手机高级系统开发工程必会技能
2、新专题投屏实战专题
车机手机投屏开发入门到精通实战课
3、aosp15之wms过渡动画ShellTransition实战专题
新课预告:ShellTransition项目实战专题aosp15版本
4、安卓音频Audio子系统实战专题
开学第一课:安卓音频框架Audio子系统实战专题--首发优惠活动
5、车机手机三分屏实战专题
2026第一课:安卓14-1车机手机三分屏实战专题--首发优惠活动

最新文章

随机文章