Android フレームワーク スレッド(ネイティブ層)

ソースの場所

Android-12.0.0_r28/system/core/libutils/include/utils/Thread.h

Android-12.0.0_r28/システム/コア/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 フレームワーク RefBase,sp,wp )

簡単な説明

Threadクラスは実際にPOSIXスレッドライブラリ ( pthread) をカプセル化し (学習については、私の記事を参照してください: Linux POSIX スレッド)、​​提供される基本的な関数は、スレッドのライフ サイクル (作成、操作、破棄) をカバーします。

メンバー関数

プライベートメソッド:

virtual bool threadLoop() = 0:

これは仮想関数であり、派生クラスはそれを実装する必要がありますthreadLoop()スレッドはここから始まります。Thread オブジェクトを使用するには、次の 2 つの方法があります。

  • ループ実行:threadLoop()が返された場合truerequestExit()呼び出されない場合は再度呼び出されます。

  • 1 回実行: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/

次に、デバイスのシェル環境に入り、実行します./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/システム/コア/libutils/Threads.cpp

スレッドを開始するとき、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 スレッドの作成および破棄メソッドをカプセル化します。

ミューテックス

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 スレッドミューテックスおよびその他の関連メソッドをカプセル化します**

状態

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 スレッド条件変数とその他の関連メソッドを実際にカプセル化します。

動作原理と概要

  1. XXXを継承しThreadthreadLoop()メソッドをオーバーライドし、必要なコードを実行する派生クラスを作成します。

  2. xxx クラスのオブジェクトを作成し、(runメソッドを介して) 実行を開始します。この時点で、Thread内部が_threadLoop()呼び出されます。

    2.1. 一度だけ実行するreadyToRun()

    2.2. 手順 1 の派生クラスをループ実行用に書き換えますthreadLoop()注: オーバーライドの戻り値は、threadLoop()ループ実行メソッドを続行するかどうかを決定します。

  3. 終了メソッド、呼び出し可能なrequestExit()関数またはrequestExitAndWait関数を要求する

おすすめ

転載: blog.csdn.net/weixin_45767368/article/details/129286765