线程启动、结束,创建线程多法、join,detach,线程的移动语义

一.范例演示线程运行的开始和结束

程序运行起来,生成一个进程,该进程所属的主线程开始自动运行;

实际上这个是主线程在执行,主线程从main函函数返回,则整个进程执行完毕。

主线程从main()开始执行,那么我们自己创建的线程,也需要从一个函数开始运行(初始函数),一旦这个函数运行完毕就代表这个线程结束。

整个进程是否执行完毕的标志是 主线程是否执行完,如果主线程执行完毕了,就代表整个进程执行完毕了;

此时,一般情况下:如果其他子线程还没有执行完毕,那么这些子线程也会被操作系统强行终止。

所以,一般情况下,如果想保持子线程(自己用代码创建的线程)的运行状态的话,那么要让主线程一直保持运行或者在子线程结束后结束。

二.创建多线程

使用 std::thread 创建子线程非常直接。最基本的方法是:构造一个 std::thread 对象,并传入一个可调用对象(函数、lambda、函数对象)作为线程的入口点

join()函数

阻塞主线程,让主线程等待子线程执行完毕后再继续往下执行。

detach()函数

分离主线程。如果不关心子线程何时结束,且子线程不会访问主线程中即将销毁的资源,可以将其分离 。分离后,子线程在后台独立运行,主线程不再能控制它

谨慎使用,分离的线程可能在主线程退出后仍在运行,访问已销毁的变量会导致未定义行为。

如果thread对象销毁时仍未join()或detach(),程序会崩溃。

头文件

cpp 复制代码
#include<iostream>
#include<thread>    //thread的头文件
using namespace std;
  1. 无参函数
    thread 对象名(函数名);

    cpp 复制代码
    void print()
    {
        cout << "子线程开始" << endl;
        //...中间代码
        cout << "子线程结束" << endl;
    }
    
    //用print构造thread对象
    thread pt(print);    //创建子线程,线程起点(入口)是print(),创建后线程开始执行
    pt.join();           //阻塞主线程,让主线程等待子线程执行完毕。
    //子线程执行完毕后join()就执行完毕,主线程继续向下执行
  2. 按值传递(默认模式)
    thread 对象名(函数名,参数1,参数2,...);

    cpp 复制代码
    void print_sum(int a, int b) {    //需要传递参数的函数,默认按值传递
        std::cout << "Sum = " << a + b << std::endl;
    }
    
    thread t(print_sum, 10, 20);  // 参数直接跟在函数名后
    t.join();
  3. 引用传递(修改值)
    thread 对象名(函数名,ref(参数1),ref(参数2),...); 不加ref会报错

    cpp 复制代码
    void modify(int& x) {        //传递引用
        x = 100;
    }
    
    int val = 0;
    thread m(modify, ref(val));  // 不加 ref 会编译错误
    m.join();
    cout << val << endl;  // 输出 100
  4. lambda表达式
    thread 对象名(捕获参数(){函数体});

    cpp 复制代码
    int local = 42;
    thread l([&local]() {
        local += 1;
        cout << "Inside thread: " << local << endl;
        });
    l.join();
    cout << "Outside: " << local << endl;
  5. 使用成员函数作为入口需要传入对象指针和成员函数指针
    thread 对象名(成员函数指针,对象指针,参数1,参数2,...);

    cpp 复制代码
    class MyClass {
    public:
        MyClass(){
        cout<<"子线程开始"<<endl;
        //...
        cout<<"子线程结束"<<endl;
        }
        void work(int n) {
            cout << "Working on " << n << endl;
        }
    };
    
    MyClass c;
    thread cla(&MyClass::work , &c, 10);
    cla.join();
    
    MyClass d;
    thread obj(d);
    obj.join();        

三.线程的移动语义

thread 是可移动但不可复制的。可以将线程的所有权转移给另一个 thread 对象:

cpp 复制代码
thread t1(hello);
thread t2 = move(t1);  // t1 不再代表任何线程
t2.join();
相关推荐
丈剑走天涯13 分钟前
JDK 17 正式特性
java·开发语言
秋田君22 分钟前
QT_QFontDialog类字体对话框
开发语言·qt
圣光SG27 分钟前
Java操作题练习(七)
java·开发语言·算法
土星云SaturnCloud1 小时前
边缘侧大模型部署的新利器——国科环宇GK 300I大模型一体机深度评测与架构解析
服务器·人工智能·ai·边缘计算
麻瓜老宋2 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十三步,多行输入、进制输出、错误恢复、常量折叠、配置加载等
c语言·开发语言·atomcode
晚风吹长发2 小时前
Docker基础——Docker Network(网络详解)
linux·运维·网络·ubuntu·docker·容器
Cx330_FCQ2 小时前
Tmux使用
服务器·git·算法
hz567892 小时前
音视频SDK核心能力分析:低延迟传输与高并发接入方案
网络·安全·音视频·实时音视频·信息与通信
q567315232 小时前
企业级 HTTP 代理采购选型:技术评估清单 15 项
开发语言·网络·爬虫·网络协议·http·隧道ip·代理ip
白嫖一茶2 小时前
HTTP 状态码详解:五大类与常见状态码解析
网络·网络协议·http