当前位置:   article > 正文

C++多线程 -- std::thread的基本用法

std::thread

依赖头文件: #include< thread >
用法: std::thread 和 join或 detach一起用
std::thread t1(调用函数名称,调用函数参数1,调用函数参数2,。。。,调用函数参数n)
t1.join(); //表示同步(阻塞),调用线程走完,才能走后面的流程
t1.detach(); //表示异步,主线程只触发此线程,后面和此线程无关

多线程传递参数

#include <iostream>
#include <thread>
void show(const char str[], const int id)
{
    std::cout << "线程: " <<id<< ",Output " << str << std::endl;
}
int main()
{
    std::thread t1(show, "hello cplusplus!", 1);
    t1.join();
    std::thread t2(show, "你好,C++!", 2);
    t2.join();
    std::thread t3(show, "hello!", 3);
    t3.join(); 
    system("pause");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述
线程交换

#include<iostream>
#include<thread>
int main()
{
    using namespace std;
    thread t1([]()
        {cout << "thread1" << endl;});
    thread t2([]()
        {cout << "thread2" << endl;});
    cout << "thread1' id is " << t1.get_id() << endl;
    cout << "thread2' id is " << t2.get_id() << endl;

    cout << "swap after:" << endl;
    swap(t1, t2);//线程交换
    cout << "thread1' id is " << t1.get_id() << endl;
    cout << "thread2' id is " << t2.get_id() << endl;
    t1.join();
    t2.join();
    system("pause");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在这里插入图片描述
线程移动

#include<iostream>
#include<thread>
int main()
{
    using namespace std;
    thread t1([]()
        {cout << "thread1" << endl;});
    cout << "thread1' id is " << t1.get_id() << endl;
    thread t2 = move(t1);
    cout << "thread2' id is " << t2.get_id() << endl;
    t2.join();
    system("pause");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述
线程的join和detach
detach();//脱离主线程的绑定,主线程挂了,子线程不报错,子线程执行完自动退出。detach以后,子线程会成为孤儿线程,线程之间将无法通信。

无论在windows中还是Posix中,主线程和子线程的默认关系是:无论子线程执行完毕与否,一旦主线程执行完毕退出,所有子线程执行都会终止。这时整个进程结束或僵死,部分线程保持一种终止执行但还未销毁的状态,而进程必须在其所有线程销毁后销毁,这时进程处于僵死状态。线程函数执行完毕退出,或以其他非常方式终止,线程进入终止态,但是为线程分配的系统资源不一定释放,可能在系统重启之前,一直都不能释放,终止态的线程,仍旧作为一个线程实体存在于操作系统中,什么时候销毁,取决于线程属性。在这种情况下,主线程和子线程通常定义以下两种关系:可会合(joinable)、相分离(detached)

#include<iostream>
#include<thread>
#include<array>
using namespace std;
void show(){cout << "hello cplusplus!" << endl;}
int main()
{
    thread th = thread(show);
    th.detach();
    cout << "是否可以join:"<<th.joinable() << endl;
    //开3个线程
    array<thread, 3>  threads = { thread(show), thread(show), thread(show) };
    for (int i = 0; i < 3; i++)
    {
        cout << threads[i].joinable() << endl;
        //判断线程是否可以join
        threads[i].join();
        //主线程等待当前线程执行完成再退出
    }
    system("pause");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这里插入图片描述
1、可会合(joinable):这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。
2、相分离(detached):表示子线程无需和主线程会合,也就是相分离的,这种情况下,子线程一旦进入终止状态,这种方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用。

在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源(如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。

join()是个简单暴力的方法:新线程调用join()之后,主线程会一直等待新进程,直到新线程执行完毕(Waits for this thread to die)。
而detach()将本线程从调用线程中分离出来,允许本线程独立执行。分离线程没有被其他的线程所等待,自己运行结束了,线程也就终止了,马上释放系统资源。但是当主进程结束的时候,即便是detach出去的子线程不管有没有完成都会被强制杀死。
简言之,main()函数结束了线程对象就析构了,如果线程没执行完那就爆炸了。
调用join阻塞,等待线程执行完毕。
调用detach放到后台,但你不能控制它了,这个时候该thread对象不代表任何线程体,joinable()=false。

参考:
C++ 并发编程之std::thread的基本用法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/153547
推荐阅读
相关标签
  

闽ICP备14008679号