如何优雅的写C++代码 Obotcha介绍(Thread类)

本文详细介绍了在Obotcha框架中实现多线程管理的具体策略,包括如何避免线程生命周期结束时引发的异常问题,通过KeepAliveThread类保存线程实例,确保线程安全退出,以及线程运行结束后触发自动释放的机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    今天开始就要开始Obotcha的Thread介绍了。其实多线程这个东东大家平时编程用的一定很多,linux C一般用pthread,C++一般用thread,说实话,为了多线程,我还看了一下《C++并发编程实战》,总的来说还是java的concurrent包提供的功能比较好用。哈哈,所以在Obotcha中专门有一个concurrent文件架来支持多线程。

    开发Thread类,主要遇到了下面几个问题:

    1.Thread类是智能指针,如果遇到下面的情况,智能指针被释放时,线程该如何处理。例如下面的代码

{
    Thread t = createThread();
    t->start()
}

t的生命周期结束后,t就会被释放,但是这个时候如果t的线程还在运行,那就会出现无法预料的情况了。但是如果让使用Thread类用户去关心t的生命周期,这显然也是不合理的。所以在这种情况下,我用了一个KeepAliveThread的类来保存所有启动的thread实例。只有当线程运行完成后,从KeepAliveThread中移除,智能指针才会做释放操作。我们看一下Obotcha Thread的start方法做了什么操作:

int _Thread::start() {
    ....

    mStatus = ThreadIdle;

    pthread_attr_init(&mThreadAttr);
    pthread_create(&mPthread, &mThreadAttr, localRun, this);
    while(bootFlag->orAndGet(0) == 0) {
        //wait
    }
    return 0;
}

pthread_create后会有一个bootFlag的循环等待,这个flag会在线程启动后设置,这么做的处理主要是为了防止在线程还未启动的时候有用户直接调stop,导致各种异常的crash。接下来,看一下localRun做了什么处理~

void* _Thread::localRun(void *th) {
    _Thread *thread = static_cast<_Thread *>(th);
    //thread->mStatus = ThreadRunning;
    KeepAliveThread mKAThread = mKeepAliveThread; 
    sp<_Thread> localThread;
    localThread.set_pointer(thread);
    mKeepAliveThread->save(localThread);
    //wangsl
    thread->bootFlag->orAndGet(1);
    //wangsl

    .....
}

mKeepAliveThread->save(localThread);这句就是将当前thread保存到了keepAliveThread中,这样就能防止thread生命周期到了自动释放的问题了。

2.线程运行结束后,如果触发自动释放

由于之前将线程的实例存放在了keepAliveThread中,所以当线程运行完成后,需要将实例移出keepAliveThread来触发自动释放。Obotcha的做法是当thread运行结束,将对应的pthread_t数值加入到释放队列,同时触发keepAlilveThread去做回收~。相关代码如下:

void* _Thread::localRun(void *th) {
    .....
    thread->mStatus = ThreadRunning;
    if(thread->mRunnable != nullptr) {
        thread->mRunnable->run();
        thread->mRunnable = nullptr;
    } else {
        thread->run();
    }
    ......
    thread->mStatus = ThreadComplete;

    mKAThread->drop(localThread->mPthread);
    
    return nullptr;
}

mKAThread->drop(localThread->mPthread);这句就是将pthread_t加入移除队列。最后我们看一下移除的操作:

void _KeepAliveThread::run() {
    //printf("RecyleThread run \n");
    //mDestroyMutex->lock();
    //if(mDestroyBarrier == 1) {
        //mDestroyMutex->unlock();
    //    return;
    //}

    ThreadLocal<Thread> tLocal = mThreadLocal;
    BlockingQueue<Uint64> mQueue = queue;
    //mDestroyMutex->unlock();

    while(1) {
        mStartBarrier->orAndGet(1);
        Uint64 t = mQueue->deQueueFirst();
        
        tLocal->remove(t->toValue());
        //can not print thread's infor,because thread may be released!!
    }
}

tLocal里面就是存放了所有运行的线程实例,如果线程运行完成,且没有任何引用,那当tLocal->remove之后,thread就会被自动释放了。

开发Thread花了大约10天左右,经历了各种线程异步导致的crash,特别是线程退出这块,是耗费了5天左右才完成所有问题的解决。这个印证了一句名言:编写一个安全退出的程序难道远大于编写一个稳定运行的程序~~。哈哈。

 

github代码:

https://github.com/wangsun1983/Obotcha/blob/master/util/concurrent/Thread.cpp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值