C ++ 11多线程–第2部分:连接和分离线程

本文探讨了C++11标准下std::thread的join和detach操作,讲解了如何通过join函数等待线程完成,以及如何使用detach创建守护线程。同时,文章强调了在调用这些函数前检查线程状态的重要性,以及在异常处理中使用资源获取初始化(RAII)模式来确保线程正确管理。

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

翻译来自:C++11 Multithreading – Part 2: Joining and Detaching Threads
在本文中,我们将讨论std :: thread的连接和分离。

用std :: thread :: join()连接线程
一旦启动一个线程,则另一个线程可以等待该新线程完成。为此,还需要在std :: thread对象上调用join()函数,即

std::thread th(funcPtr);
// Some Code
th.join();

让我们来看一个例子
假设主线程必须启动10个工作线程,并且在启动所有这些线程之后,主函数将等待它们完成。加入所有线程后,main函数将继续,

#include <iostream>
#include <thread>
#include <algorithm>
class WorkerThread
{
public:
    void operator()()     
    {
        std::cout<<"Worker Thread "<<std::this_thread::get_id()<<" is Executing"<<std::endl;
    }
};
int main()  
{
    std::vector<std::thread> threadList;
    for(int i = 0; i < 10; i++)
    {
        threadList.push_back( std::thread( WorkerThread() ) );
    }
    // Now wait for all the worker thread to finish i.e.
    // Call join() function on each of the std::thread object
    std::cout<<"wait for all the worker thread to finish"<<std::endl;
    std::for_each(threadList.begin(),threadList.end(), std::mem_fn(&std::thread::join));
    std::cout<<"Exiting from Main Thread"<<std::endl;
    return 0;
}

使用std :: thread :: detach()分离线程
分离的线程也称为守护程序/后台线程。要分离线程,我们需要在std :: thread对象上调用std :: detach()函数,即

std::thread th(funcPtr);
th.detach();

调用detach()之后,std :: thread对象不再与实际的执行线程关联。
在线程句柄上调用detach()和join()时要小心
情况1:永远不要在没有关联执行线程的std :: thread对象上调用join()或detach()

std::thread threadObj( (WorkerThread()) );
    threadObj.join();
    threadObj.join(); // It will cause Program to Terminate

当在线程对象上调用join()函数时,则当此join(0返回时,则std :: thread对象没有与其关联的线程。如果再次在该对象上调用join()函数,则将导致终止程序。
同样,调用detach()可以使std :: thread对象不与任何线程函数链接。在那种情况下,在std :: thread对象上调用detach(0函数两次)将导致程序终止。

std::thread threadObj( (WorkerThread()) );
    threadObj.detach();
    threadObj.detach(); // It will cause Program to Terminate

因此,在调用join()或detach()之前,我们应该每次检查线程是否可连接,即

 std::thread threadObj( (WorkerThread()) );
    if(threadObj.joinable())
    {
        std::cout<<"Detaching Thread "<<std::endl;
        threadObj.detach();
    }
    if(threadObj.joinable())    
    {
        std::cout<<"Detaching Thread "<<std::endl;
        threadObj.detach();
    }
    
    std::thread threadObj2( (WorkerThread()) );
    if(threadObj2.joinable())
    {
        std::cout<<"Joining Thread "<<std::endl;
        threadObj2.join();
    }
    if(threadObj2.joinable())    
    {
        std::cout<<"Joining Thread "<<std::endl;
        threadObj2.join();
    }

情况2 :永远不要忘记在具有关联执行线程的std :: thread对象上调用join或detach
如果在具有关联执行线程的std :: thread对象中 均未调用join或detach,则在该对象的destruct-期间它将-终止程序。 因为在destruct-or里面检查线程是否仍然可以连接,然后终止程序,即

#include <iostream>
#include <thread>
#include <algorithm>
class WorkerThread
{
public:
    void operator()()     
    {
        std::cout<<"Worker Thread "<<std::endl;
    }
};
int main()  
{
    std::thread threadObj( (WorkerThread()) );
    // Program will terminate as we have't called either join or detach with the std::thread object.
    // Hence std::thread's object destructor will terminate the program
    return 0;
}

同样,在发生异常的情况下,我们不应忘记调用join()或detach()。为了防止这种情况,我们应该使用“资源获取初始化”(RAII),即

#include <iostream>
#include <thread>
class ThreadRAII
{
    std::thread & m_thread;
    public:
        ThreadRAII(std::thread  & threadObj) : m_thread(threadObj)
        {
            
        }
        ~ThreadRAII()
        {
            // Check if thread is joinable then detach the thread
            if(m_thread.joinable())
            {
                m_thread.detach();
            }
        }
};
void thread_function()
{
    for(int i = 0; i < 10000; i++);
        std::cout<<"thread_function Executing"<<std::endl;
}
 
int main()  
{
    std::thread threadObj(thread_function);
    
    // If we comment this Line, then program will crash
    ThreadRAII wrapperObj(threadObj);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值