美文网首页C++编程软件开发
C++11多线程-【2】线程的join和detach

C++11多线程-【2】线程的join和detach

作者: 雪域迷影 | 来源:发表于2021-05-04 09:00 被阅读0次

    C++11多线程-【2】线程的join和detach

    本文翻译自 C++11 Multithreading – Part 2: Joining and Detaching Threads,转载自C++11多线程-【2】线程的join和detach

    本文介绍线程对象 std::thread 的 joining 和 detaching。

    使用 std::thread::join() 进行线程的 joining

    一旦一个线程开始之后,另一个线程可以等待此线程结束。

    需要等待的线程可以调用 std::thread 的 join() 函数来实现上述功能。

    std::thread th(funcPtr);
    //some code
    th.join();
    

    下面看一个简单的例子。

    假设主线程需要启动 10 个工作线程,开始这些线程之后,主线程需要等待这些线程结束。等 joining 所有的线程之后,主程序继续运行:

    #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(void) {
        std::vector<std::thread> threadList;
        for (int i = 0; i < 10; i++) {
            threadList.push_back(std::thread(WorkerThread()));
        }
        // 等待所有的工作线程结束,即对每一个 std::thread 对象调用 join() 函数
        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() 进行线程的 detaching

    detached 线程也被称为守护/后台进程。对线程进行 detached(翻译成分离?)操作,需要使用对 std::thread 对象调用 std::detach() 。

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

    小心调用线程的 detach() 和 join()

    案例1:不要在没有相关执行线程的 std::thread 对象上调用 join() 或 detach()

    std::thread threadObj( (WorkerThread()) );
    threadObj.join();
    threadObj.join(); // 会导致程序中断
    

    对线程对象调用 join() 函数,则当这个 join() 返回时,std::thread 对象就没有了与之相关联的线程。对这样的 std::thread 对象再次进行 join() 函数调用时,就会导致程序中断。

    同理,调用 detach() 一样会使得 std::thread 对象不与其他任何的线程关联。在这种情况下,再次调用 detach() 会中断程序。

    std::thread threadObj( (WorkerThread()) );
    threadObj.detach();
    threadObj.detach(); // 会导致程序中断
    

    因此,在调用 join() 或者 detach() 之前,我们每次都应该检查线程是否是 join-able 的。

    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() 也没有调用 thread(),则在对象的析构的过程中会中断程序。例:

    #include <iostream>
    #include <thread>
    #include <algorithm>
    
    class WorkerThread {
    public:
        void operator()() {
            std::cout << "Worker Thread " << std::endl;
        }
    };
    
    int main(void) {
        std::thread threadObj((WorkerThread()));
        // 程序会中断,因为既没有调用 join() 也没有调用 detach()
        return 0;
    }
    

    同样在异常情况下,我们也不能忘记调用 join() 或者 detach()。

    为了防止这种情况,我们应该使用 ESOURCE ACQUISITION IS INITIALIZATION (RAII)。例:

    #include <iostream>
    #include <thread>
    
    class ThreadRAII {
        std::thread &m_thread;
        public:
        ThreadRAII(std::thread &threadObj) : m_thread(threadObj) {}
        ~ThreadRAII() {
            // 假如 joinable 则调用 detach
            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(void) {
        std::thread threadObj(thread_function);
        
        // 注释掉这行,程序会 crash
        ThreadRAII wrapperObj(threadObj);
        return 0;
    }
    

    下一篇::C++11多线程 -【3】传参给线程

    相关文章

      网友评论

        本文标题:C++11多线程-【2】线程的join和detach

        本文链接:https://www.haomeiwen.com/subject/hbhcdltx.html