C++11 多线程 ——detach、join

#include <iostream>
#include <thread>

void function_1() {
    std::cout << "I'm function_1()" << std::endl;
}

int main() {
    std::thread t1(function_1);
    // do other things
    t1.join();
    return 0;
}

创建一个std::thread 对象 t1, 构造时传递一个callable参数, 作为这个线程的入口,线程对象创建成功后,线程也就成功启动了,

直到入口函数执行完毕,线程也就执行完成了。

当执行例程返回后,线程就会终止,这时候需要回收线程的资源。有两种方式指定回收的方式:

  • join: 调用线程等待线程对象关联的执行线程执行结束,然后回收它的资源。
  • detach:调用线程不希望等待,因此将线程对象和它关联的执行线程分离,交由 C++ Runtime管理该执行线程。

一个被分离的线程也成为守护线程(daemon thread),概念与Linux的守护线程相似,这类线程通常都长期运行于后台。

一个线程对象要么被join, 要么被detach。 如果两者都无, 那么线程对象在析构时会调用 std::terminate, 使得程序异常结束。可以通过调用thread::joinable判断线程是否可以被join或 detach。

上面代码使用了 t1.join(), 主线程会一直阻塞着,直到子线程完成,join()函数的另一个任务是回收该线程中的资源。 但是我们通常不想这么做,因为我们使用多线程,是为了提高并发度。如果创建一个线程之后就把另一个线程投入等待,那么程序的并发度就得不到提高。

线程对象和对象内部管理的生命周期并不一样,如果线程执行得快,可能内部的线程已经结束了,但是线程对象还活着,也有可能线程对象已经被析构了,但是内部的线程还在运行。

假设t1线程是一个执行很慢的进程,主线程并不想等子线程结束就想结束整个任务,这时我们可以选择调用t1.detach(), 从而将t1线程放在后台运行,所有权和控制权交给C++运行时库。这样,线程被分离之后,即使该线程对象被析构了,线程还是能够在后台运行,只是由于对象被析构了,主线程不能通过对象名与这个线程进行通信。 例如:

#include <iostream>
#include <thread>

void function_1() {
    //延时500ms 为了保证test()运行结束之后才打印
    std::this_thread::sleep_for(std::chrono::milliseconds(500)); 
    std::cout << "I'm function_1()" << std::endl;
}

void test() {
    std::thread t1(function_1);
    t1.detach();
    // t1.join();
    std::cout << "test() finished" << std::endl;
}

int main() {
    test();
    //让主线程晚于子线程结束
    std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //延时1s
    return 0;
}

// 使用 t1.detach()时
// test() finished
// I'm function_1()

// 使用 t1.join()时
// I'm function_1()
// test() finished

由于线程入口函数内部有个500ms的延时,所以在还没有打印的时候,test()就已经执行完成了,t1对象已经被析构了,但是它负责的那个线程还是能够运行。

如果去掉main中1s的延时,会发现

I'm function_1()

没有输出, 这是因为主线程执行太快,整个程序已经结束了,那个后台线程被C++运行时库回收了。

如果将t1.detach()换成t1.join(), test函数会在t1线程执行结束之后,才执行结束。

一旦一个线程被分离了,就不能再被join了。

参考:http://blog.leanote.com/post/gaunthan/C-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BA%BF%E7%A8%8B%E7%AE%A1%E7%90%86

猜你喜欢

转载自blog.csdn.net/zhhp1001/article/details/88085289