必须用 pthread 而非 std::thread,因 Android NDK(尤其 r21 前)缺完整 STL 线程支持,std::thread 会链接失败或运行时崩溃;pthread_create 稳定可用,但需正确管理 JNIEnv、mutex 初始化、cond 配对锁及对象值语义。

直接用 pthread,别碰 std::thread —— Android NDK 默认不提供完整 STL 线程支持,std::thread 在多数 NDK 版本(尤其是 r21 及更早)中不可用或行为异常,强行启用会链接失败或运行时崩溃。
为什么必须用 pthread 而不是 C++11 线程库
NDK 自 r18 起默认只带 libc++,但它的 std::thread 实现依赖于系统级 pthread 封装,而 Android 的 Bionic libc 对 __pthread_create 等底层符号的支持不完整。实测中:std::thread 构造可能成功,但调用 join() 或 detach() 时大概率触发 SIGABRT 或静默退出。
-
pthread_create是 Android 内核和 Bionic 直接支持的稳定接口,所有 NDK 版本都可用 - NDK 的
libc++_shared.so不导出std::thread所需的全部符号,即使编译通过,运行时也找不到__gthread_create - 如果你硬要开
-D_GLIBCXX_USE_C99=ON或切换 STL,反而会破坏 JNI 兼容性,得不偿失
pthread_create 在 JNI 函数里怎么安全调用
不能在 Java 层传进来的 JNIEnv* 里直接创建线程并复用它——子线程没有自己的 JNIEnv,一调 JNI 函数就崩。
- 主线程拿到的
JNIEnv*绝对不能跨线程保存或传递 - 必须提前缓存全局
JavaVM*(比如在JNI_OnLoad里存到静态变量g_jvm) - 子线程入口函数第一件事是调
g_jvm->AttachCurrentThread(&env, nullptr)拿本线程的JNIEnv* - 退出前必须调
g_jvm->DetachCurrentThread(),否则局部引用表泄漏、后续 Attach 失败 - 别忘了
pthread_join或pthread_detach,否则线程资源不释放,反复创建会耗尽系统线程数
多线程访问共享数据时,pthread_mutex_t 初始化不能传 nullptr
很多示例代码写 pthread_mutex_init(&mutex, nullptr),这在 Android 上会 crash —— Bionic 要求传入有效的 pthread_mutexattr_t* 或显式传 PTHREAD_MUTEX_INITIALIZER 宏(静态初始化),动态初始化必须用 attr 对象。
Android 开发调试技能,通过系统 ADB 工具操作 Android 设备。以下场景必须触发此技能:(1) 直接 ADB 操作——安装 APK、查看设备列表、抓取 logcat 日志、查看已安装应用、清除应用数据、截图、重启设备、拉取/推送文件、查看 CPU/内存/电池信息、adb shell 操作;(2)...
立即学习“C++免费学习笔记(深入)”;
- 推荐静态初始化:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - 若需动态初始化(比如在类构造函数里),先声明 attr:
pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutex_init(&mutex, &attr); pthread_mutexattr_destroy(&attr); - 漏掉
pthread_mutex_destroy会导致 native 内存泄漏,且下次 init 失败返回EBUSY - 不要用
std::mutex替代——它底层仍走 pthread,但在 NDK 中未完全适配 Bionic 的锁实现,偶发死锁
pthread_cond_wait 必须和 pthread_mutex_lock 成对出现
条件变量不是独立同步原语,它必须绑定一个已加锁的互斥量,否则调用 pthread_cond_wait 会直接返回 EINVAL 并阻塞失败。
-
pthread_cond_wait(&cond, &mutex)会原子地:解锁mutex+ 挂起线程 + 等待 signal/broadcast + 重新加锁mutex - 所以调用前必须确保当前线程已持有
mutex,否则行为未定义 - 唤醒后一定要检查谓词(比如队列是否非空),因为存在虚假唤醒(spurious wakeup)
- 别用
std::condition_variable——它在 NDK 中依赖std::mutex,同样面临初始化和 ABI 兼容问题
最易被忽略的一点:所有 pthread 对象(pthread_t、pthread_mutex_t、pthread_cond_t)都是值类型,不能 memcpy 或跨线程赋值;它们内部包含指向内核对象的指针或状态字,随意拷贝会导致后续 lock/wait 崩溃或静默失败。

















