源码位置
android-12.0.0_r28/system/core/libutils/include/utils/Thread.h
android-12.0.0_r28/system/core/libutils/Threads.cpp
android-12.0.0_r28/system/core/libutils/include/utils/Mutex.h
android-12.0.0_r28/system/core/libutils/include/utils/Condition.h
android-12.0.0_r28/system/core/libutils/include/utils/RefBase.h
(RefBase
是用于记录对象被引用的次数,可参考我这篇进行学习:Android framework RefBase,sp,wp)
简述
Thread
类其实就是封装了 POSIX
线程库(pthread
)(可参考我这篇进行学习:Linux的POSIX线程),提供的基础功能涵盖了线程的生命周期:创建、运行、销毁。
成员函数
私有方法:
virtual bool threadLoop() = 0
:
这是一个虚函数,派生类必须实现threadLoop()
。线程从这里开始它的生命。有两种使用Thread对象的方式:
-
循环执行:如果
threadLoop()
返回true
,如果requestExit()
没有被调用,它将再次被调用。 -
执行一次:如果
threadLoop()
返回false
,线程将在返回时退出。
公有方法:
virtual status_t run(const char* name, int32_t priority = PRIORITY_DEFAULT,size_t stack = 0)
:
启动线程时,需要调用该方法run
virtual void requestExit()
:
让这个对象的线程退出。这个函数是异步的,当函数返回时,线程可能仍然在运行。当然,这个函数可以从不同的线程调用。
virtual status_t readyToRun()
:
在开始循环执行或者执行一次threadLoop()
之前会调用该方法readyToRun()
,可在线程运行前执行一次初始化或者不耗时的操作。
status_t requestExitAndWait()
:
调用requestExit()
并等待,直到该对象的线程退出,这种情况下,会阻塞线程,所以要特别注意死锁。
status_t join()
:
等待这个对象的线程退出。如果尚未运行,则立即返回。如果仍在运行,则会阻塞线程,直到等待线程执行完后返回
bool isRunning() const
:
表示此线程是否正在运行。
实例
MyThread.cpp
#include <utils/Thread.h>
#include <utils/RefBase.h>
#include <stdio.h>
using namespace android;
class MyThread : public Thread {
private:
int count = 0;
public:
MyThread() {
printf("MyThread created\n"); }
bool threadLoop() {
printf("threadLoop count = %d\n",count);
count--;
if (count == 0) {
return false;
}
return true;
}
status_t readyToRun(){
count = 10;
printf("readyToRun init the count = %d\n",count);
return OK;
}
};
int main(){
sp<MyThread> myThread = new MyThread();
myThread->run("MyThread"); //看源码分析
printf("error=%s", strerror(errno));
return 0;
}
/*
执行结果
MyThread ---created
readyToRun init the count = 10
threadLoop count = 10
threadLoop count = 9
threadLoop count = 8
threadLoop count = 7
threadLoop count = 6
threadLoop count = 5
threadLoop count = 4
threadLoop count = 3
threadLoop count = 2
threadLoop count = 1
*/
把MyThread.cpp
放到Android
源码编译(我的是android-12.0.0_r28
),然后编写它的Android.bp
cc_binary {
name: "MyThread",
srcs: ["MyThread.cpp"],
shared_libs: ["libutils"],
cflags: [
"-Wno-unused-variable",
"-Wno-unused-parameter",
],
}
将生成的二进制文件MyThread
(一般在out/target/product/xxxx/system/bin/MyThread
),push
进设备的/system/bin/
目录,
再进入设备的shell环境,执行./system/bin/MyThread
adb push \xxx\out\target\product\xxx\system\bin\MyThread /system/bin
adb shell
xxxxx:/ # ./system/bin/MyThread
源码分析
android-12.0.0_r28/system/core/libutils/Threads.cpp
Thread
启动线程时,我们会主动调用run
方法,看看run
方法做了哪些操作,
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
LOG_ALWAYS_FATAL_IF(name == nullptr, "thread name not provided to Thread::run");
//获取自动锁,当变量_l被释放了,就会自动解锁。看Mutex分析
Mutex::Autolock _l(mLock);
//如果线程在运行,则返回非法操作
if (mRunning) {
// thread already started
return INVALID_OPERATION;
}
//...省略一堆代码
//判断是否在退出
mExitPending = false;
//...省略一堆代码
bool res;
//从Thread 默认的构造方法看,mCanCallJava的值默认为true,
if (mCanCallJava) {
//1.1、最终会调用到Threap中的androidCreateRawThreadEtc
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
...
return OK;
}
int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName __android_unused,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
//...省略一堆代码
//1.2、所以android native 层的Thread,其实是用了POSIX线程中的pthread_create方法创建的,
//而线程执行体就是_threadLoop()方法
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
//...省略一堆代码
}
int Thread::_threadLoop(void* user)
{
// 派生派(即上面实例的MyThread类)
Thread* const self = static_cast<Thread*>(user);
//...省略一堆代码
bool first = true;
do {
bool result;
//进入do while 循环
if (first) {
first = false;
//1.3、通过first变量,从true到false,来判断第一次进入时调用readyToRun()
self->mStatus = self->readyToRun();
result = (self->mStatus == OK);
//readyToRun是OK的并且线程是没有退出动作时,
//就会调用成员函数threadLoop(),即会调会子类的threadLoop(),
if (result && !self->exitPending()) {
// Binder threads (and maybe others) rely on threadLoop
// running at least once after a successful ::readyToRun()
// (unless, of course, the thread has already been asked to exit
// at that point).
// This is because threads are essentially used like this:
// (new ThreadSubclass())->run();
// The caller therefore does not retain a strong reference to
// the thread and the thread would simply disappear after the
// successful ::readyToRun() call instead of entering the
// threadLoop at least once.
result = self->threadLoop();
}
} else {
//
result = self->threadLoop();
}
// establish a scope for mLock
{
Mutex::Autolock _l(self->mLock);
//1.4根据派生类重写threadLoop()的返回值,判断继续循环或者只执行一次,
//并把设置相关状态mExitPending和mRunning
if (result == false || self->mExitPending) {
self->mExitPending = true;
self->mRunning = false;
//...省略一堆代码
//当调用requestExitAndWait时,如果线程还在运行,就会阻塞,
//当线程完成后,就会通过条件变量mThreadExitedCondition.broadcast()唤醒在等待中的线程。
//看Condition分析
self->mThreadExitedCondition.broadcast();
break;
}
}
//...省略一堆代码
} while(strong != nullptr);//1.5 继续下一轮的循环
return 0;
}
所以,Thread类其实就是封装了Linux的POSIX线程创建和销毁等相关方法
Mutex
android-12.0.0_r28/system/core/libutils/include/utils/Mutex.h
//...省略一堆代码
inline Mutex::Mutex() {
//调用POSIX的初始化互斥锁
pthread_mutex_init(&mMutex, nullptr);
}
//...省略一堆代码
inline status_t Mutex::lock() {
//调用POSIX的获取互斥锁
return -pthread_mutex_lock(&mMutex);
}
inline void Mutex::unlock() {
//调用POSIX的释放互斥锁
pthread_mutex_unlock(&mMutex);
}
//...省略一堆代码
class SCOPED_CAPABILITY Autolock {
//SCOPED_CAPABILITY是宏定义
public:
//在构造和析造函数里分别获取锁和释放锁,即某变量在某代码段被回收了,就会调用析造函数从而自动解锁。防止死锁或者自己忘记解锁操作。
inline explicit Autolock(Mutex& mutex) ACQUIRE(mutex) : mLock(mutex) {
mLock.lock(); }
inline explicit Autolock(Mutex* mutex) ACQUIRE(mutex) : mLock(*mutex) {
mLock.lock(); }
inline ~Autolock() RELEASE() {
mLock.unlock(); }
private:
Mutex& mLock;
// Cannot be copied or moved - declarations only
Autolock(const Autolock&);
Autolock& operator=(const Autolock&);
};
// 所以Autolock在自己的生命周期内,自动加锁也会自动放锁的类
typedef Mutex::Autolock AutoMutex;
//...省略一堆代码
Mutex类其实就是封装了Linux的POSIX线程互斥锁等相关方法**
Condition
android-12.0.0_r28/system/core/libutils/include/utils/Condition.h
//...省略一堆代码
inline status_t Condition::wait(Mutex& mutex) {
//调用POSIX的条件变量:等待某个条件变量的线程广播一个信号
return -pthread_cond_wait(&mCond, &mutex.mMutex);
}
//...省略一堆代码
inline void Condition::signal() {
//调用POSIX的条件变量:向等待某个条件变量的线程广播一个信号,唤醒一个等待在条件变量上的线程
pthread_cond_signal(&mCond);
}
inline void Condition::broadcast() {
//调用POSIX的条件变量:向等待某个条件变量的线程广播一个信号,以唤醒所有等待该条件变量的线程
pthread_cond_broadcast(&mCond);
}
//...省略一堆代码
Condition类其实就是封装了Linux的POSIX线程条件变量等相关方法
工作原理与总结
-
创建派生类
XXX
继承Thread
,重写threadLoop()
方法,执行所需要的代码. -
创建xxx类对象,并启动运行(通过
run
方法),此时Thread
内部会在_threadLoop()
调用:2.1. 只执行一次
readyToRun()
2.2. 循环执行步骤1中派生类重写的
threadLoop()
。注意:重写的threadLoop()
返回值确定是否继续循环执行的方法。 -
请求退出方法,可调用
requestExit()
函数或者requestExitAndWait
函数