创建多线程 std::thread,join(),detach()

中文文档:原子操作std::atomic(可以无锁并发编程)

中文文档:线程支持库

参考:C++:线程(std::thread)

转载:C++多线程

一、std::thread创建多线程

点击查看代码
#include <iostream>
#include <thread>

void fun1()
{
    for (int i = 0; i < 10; i++)
    {
        std::cout << "1" << "2" << std::endl;
    }
}
void fun2()
{
    for (int i = 0; i < 10; i++)
    {
        std::cout << "3" << "4" <<  std::endl;
    }
}
int main() 
{
    std::cout << "main start" << std::endl;
    std::thread t1(fun1);
    std::thread t2(fun2);
    std::cout << "main end" << std::endl;

    return 0;
}

结果

可以看到,这样创建线程是有问题的,因为在创建了线程后线程开始执行,但是主线程main()并没有停止脚步,仍然继续执行然后退出,此时线程对象还是joinable(可结合的)的,线程仍然存在但指向它的线程对象已经销毁,所以会抛出异常。

二、如何保证子线程执行完了退出后再退出主线程呢?

1.使用join()

使用join接口可以解决上述问题,join的作用是让主线程等待直到该子线程执行结束(因此调用join会阻塞)。需要注意的是线程对象执行了join后就不再joinable了,所以只能调用join()一次。创建了线程之后并不是调用join或detach才会执行线程,也许调用join或detach之前线程已经执行完了。只要创建了线程对象(传递“函数名/可调用对象”作为参数的情况下),线程就开始执行(std::thread 有一个无参构造函数重载的版本,不会创建底层的线程,只是一个空的对象。)。

1)join()阻塞代码演示

点击查看代码
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>

using namespace std;

void work()
{
    this_thread::sleep_for(chrono::seconds(5));
}

int main()
{
    clock_t start = clock();
    vector<thread> t;
    for (int i = 0; i < 5; i++)
    {
        t.emplace_back(thread(work));
        //t[i].join();  //join放在这里程序运行时间为25s多一点
    }
    for (int i = 0; i < 5; i++)
    {       //join放在这里程序运行时间为5s多一点
        t[i].join();  //join会阻塞住,因此需要放在创建线程的循环外边才能达到多线程的效果
    }
    cout << clock() - start;
}

2)join()使用演示

点击查看代码
#include <iostream>
#include <thread>

void fun1()
{
    for (int i = 0; i < 10; i++)
    {
        std::cout << "1" << "2" << std::endl;
    }
}
void fun2()
{
    for (int i = 0; i < 10; i++)
    {
        std::cout << "3" << "4" <<  std::endl;
    }
}

int main() 
{
    std::cout << "main start" << std::endl;
    std::thread t1(fun1);
    std::thread t2(fun2);
    std::cout << "***" << std::endl;
    t1.join();
    std::cout << "@@@" << std::endl;
    t2.join();
    std::cout << "main end" << std::endl;

        //std::thread(fun1).join();  //和上面两句代码等价
    return 0;
}

创建多线程 std::thread,join(),detach()

2. 使用detach()

detach是用来和线程对象分离的,这样线程可以独立地执行,不过这样由于没有thread对象指向该线程而失去了对它的控制,当对象析构时线程会继续在后台执行,但是当主程序退出时并不能保证线程能执行完。如果没有良好的控制机制或者这种后台线程比较重要,最好不用detach而应该使用join。

点击查看代码
#include <iostream>
#include <thread>

void fun1()
{
    for (int i = 0; i < 10; i++)
    {
        std::cout << "1" << "2" << std::endl;
    }
}
void fun2()
{
    for (int i = 0; i < 10; i++)
    {
        std::cout << "3" << "4" <<  std::endl;
    }
}
int main() 
{
    std::cout << "main start" << std::endl;
    std::thread t1(fun1);
    std::thread t2(fun2);
    std::cout << "***" << std::endl;
    t1.detach();
    std::cout << "@@@" << std::endl;
    t2.detach();
    std::cout << "main end" << std::endl;

    return 0;
}

创建多线程 std::thread,join(),detach()

由结果可见线程并没有执行完而退出

三、std::thread调用含有参数,带有返回值的函数以及成员函数

std::thread调用带参数和返回值的函数

原文链接: https://www.cnblogs.com/mmmmmmmmm/p/14574473.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    创建多线程 std::thread,join(),detach()

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/404188

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月24日 下午6:44
下一篇 2023年4月24日 下午6:44

相关推荐