AI代码分析 - LocklessQueue

services\surfaceflinger\LocklessQueue.h

cpp 复制代码
// Single consumer multi producer queue. We can understand the two operations independently to see
// why they are without race condition.
//
// push is responsible for maintaining a linked list stored in mPush, and called from multiple
// threads without lock. We can see that if two threads never observe the same value from
// mPush.load, it just functions as a normal linked list. In the case where two threads observe the
// same value, one of them has to execute the compare_exchange first. The one that doesn't execute
// the compare exchange first, will receive false from compare_exchange. previousHead is updated (by
// compare_exchange) to the most recent value of mPush, and we try again. It's relatively clear to
// see that the process can repeat with an arbitrary number of threads.
//
// Pop is much simpler. If mPop is empty (as it begins) it atomically exchanges
// the entire push list with null. This is safe, since the only other reader (push)
// of mPush will retry if it changes in between it's read and atomic compare. We
// then store the list and pop one element.
//
// If we already had something in the pop list we just pop directly.
template <typename T>
class LocklessQueue {
public:
    bool isEmpty() { return (mPush.load() == nullptr) && (mPop.load() == nullptr); }

    void push(T value) {
        Entry* entry = new Entry(std::move(value));
        Entry* previousHead = mPush.load(/*std::memory_order_relaxed*/);
        do {
            entry->mNext = previousHead;
        } while (!mPush.compare_exchange_weak(previousHead, entry)); /*std::memory_order_release*/
    }

    std::optional<T> pop() {
        Entry* popped = mPop.load(/*std::memory_order_acquire*/);
        if (popped) {
            // Single consumer so this is fine
            mPop.store(popped->mNext /* , std::memory_order_release */);
            auto value = std::move(popped->mValue);
            delete popped;
            return value;
        } else {
            Entry* grabbedList = mPush.exchange(nullptr /* , std::memory_order_acquire */);
            if (!grabbedList) return std::nullopt;
            // Reverse the list
            while (grabbedList->mNext) {
                Entry* next = grabbedList->mNext;
                grabbedList->mNext = popped;
                popped = grabbedList;
                grabbedList = next;
            }
            mPop.store(popped /* , std::memory_order_release */);
            auto value = std::move(grabbedList->mValue);
            delete grabbedList;
            return value;
        }
    }

private:
    class Entry {
    public:
        T mValue;
        std::atomic<Entry*> mNext;
        Entry(T value) : mValue(value) {}
    };
    std::atomic<Entry*> mPush = nullptr;
    std::atomic<Entry*> mPop = nullptr;
};

LocklessQueue 类解析

源文件:services/surfaceflinger/LocklessQueue.h

概述

这是一个无锁队列 ,采用经典的 MPSC(Multi-Producer Single-Consumer) 模式,即多线程 push、单线程 pop。在 SurfaceFlinger 中主要用于从多个线程安全地收集输入事件/消息,然后在主线程统一消费处理。

核心数据结构

cpp 复制代码
class Entry {
public:
    T mValue;
    std::atomic<Entry*> mNext;
    Entry(T value) : mValue(value) {}
};

std::atomic<Entry*> mPush = nullptr;  // 多线程 push 进来的链表(栈结构,LIFO)
std::atomic<Entry*> mPop  = nullptr;  // 给消费者 pop 用的链表(FIFO 顺序)

示意图:

css 复制代码
mPush → [entry] → [entry] → ...    (多线程并发插入,栈式 LIFO)
mPop  → [entry] → [entry] → ...    (消费者 pop 使用,队列式 FIFO)

push ------ 多线程安全入队

cpp 复制代码
void push(T value) {
    Entry* entry = new Entry(std::move(value));
    Entry* previousHead = mPush.load();
    do {
        entry->mNext = previousHead;
    } while (!mPush.compare_exchange_weak(previousHead, entry));
}

原理:

  1. 创建新节点 entry
  2. 读取当前 mPush 头节点 previousHead
  3. entry->mNext 指向 previousHead
  4. CAS(compare_exchange_weak) 尝试将 mPush 更新为 entry
  5. 如果 CAS 失败(说明其他线程已经修改了 mPush),previousHead 会被自动更新为最新值,重试

这是标准的 Treiber Stack 模式。如果多个线程同时读到同一个 head,只有一个 CAS 会成功,失败的线程会拿到更新后的 head 值并重试,保证了无锁安全。

pop ------ 单消费者出队

cpp 复制代码
std::optional<T> pop() {
    Entry* popped = mPop.load();
    if (popped) {
        // 情况1:mPop 非空,直接从 mPop 链表头部取走
        mPop.store(popped->mNext);
        auto value = std::move(popped->mValue);
        delete popped;
        return value;
    } else {
        // 情况2:mPop 为空,从 mPush 链表批量转移
        Entry* grabbedList = mPush.exchange(nullptr);
        if (!grabbedList) return std::nullopt;
        // 反转链表(LIFO → FIFO)
        while (grabbedList->mNext) {
            Entry* next = grabbedList->mNext;
            grabbedList->mNext = popped;
            popped = grabbedList;
            grabbedList = next;
        }
        mPop.store(popped);
        auto value = std::move(grabbedList->mValue);
        delete grabbedList;
        return value;
    }
}

分两种情况:

情况 1:mPop 非空

直接从 mPop 链表头部取走一个节点,O(1) 操作。由于是单消费者,不需要同步。

情况 2:mPop 为空

  1. exchange 一次性 把整个 mPush 链表偷过来(原子操作,同时将 mPush 置为 nullptr)
  2. 反转链表:因为 push 端是栈式 LIFO 插入的,反转后恢复 FIFO 顺序
  3. 将反转后的链表挂到 mPop 上(最后一个节点直接返回其值)
  4. 返回第一个元素

关键设计点

特性 说明
无锁 push CAS 循环保证多线程安全,无 mutex
批量转移 pop 空时一次性将 push 链表整体搬到 pop 链表,减少争用
反转链表 push 端是 LIFO,反转后变 FIFO,保证正确的出队顺序
内存序 代码中注释掉了显式 memory_order,使用默认的 seq_cst,保证了正确性但性能略有牺牲
单消费者约束 pop 只能从一个线程调用,否则 mPop 的读写会有数据竞争

潜在问题

  1. isEmpty 不是线程安全的 :读取 mPushmPop 之间可能被其他线程修改,结果不一定准确,只能作为启发式判断。
  2. 内存泄漏风险:析构函数没有清理链表,如果队列销毁时还有未 pop 的元素,会泄漏。
  3. 无边界:没有容量限制,理论上可以无限 push,没有背压(back-pressure)机制。
  4. 逐个 new/delete :每次 push 都 new 一个节点,pop 时 delete,有内存分配开销。

总结

LocklessQueue 是一个轻量级的无锁 MPSC 队列,通过 CAS 实现多线程安全的 push,通过原子 exchange 实现高效的批量链表转移,适合"多生产者高频写入、单消费者批量消费"的场景,与 SurfaceFlinger 的主线程消息循环模型高度契合。

相关推荐
峥嵘life2 小时前
Android 无线投屏相关知识介绍
android·学习
常利兵2 小时前
安卓开发避坑指南:全局异常捕获与优雅处理实战
android·服务器·php
studyForMokey2 小时前
【Android面试】OkHttp & Retrofit 专题
android·okhttp·面试
恋猫de小郭2 小时前
抖音“极客”适配 Android 5 ~ 9 等老机型技术解读,都是骚操作
android·前端·flutter
黄林晴2 小时前
Android Studio Panda 4 来了!AGP 9.2 升级,同步稳定性大幅修复
android·android studio
默 语2 小时前
OpenClaw“养龙虾“热潮降温的深层解析:从技术狂欢到理性回归
android·开发语言·kotlin
xiaoshiquan12062 小时前
Android16系统内容全屏,状态栏和导航栏透明
android
Carson带你学Android2 小时前
编译更快、语法更香?一文看懂 Kotlin 2.3.20 的 6 大核心演进
android·kotlin
jwn9992 小时前
Laravel3.x经典特性全解析
android