线程启动、结束,创建线程多法、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();
相关推荐
apcipot_rain12 小时前
C++转Java日记(04)
java·开发语言·c++
云和数据.ChenGuang14 小时前
LangGraph 异步 Node 的设计与写法实践
开发语言·人工智能·python·机器学习·php
WL学习笔记15 小时前
vector模拟实现
c++
天诰15 小时前
SA-K-11 检索会消失吗与四个未解问题
java·服务器·人工智能·python·机器学习·ai编程
陈希12316 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
蜗牛一步步往上爬17 小时前
第十六章 C++语言在深度学习中的应用
开发语言·c++·深度学习
女神下凡17 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
@兽血沸腾18 小时前
Windows系统安装Jenkins部署应用至远程Windows服务器操作指南
运维·服务器·jenkins
张张123y19 小时前
DSH 插件调试避坑:client.js 设置面板、热重载与高频报错排查表
开发语言·javascript·人工智能·开源·ecmascript·后端开发·ai agent
wo_jack21 小时前
C++ 入门笔记(十六):第16课 vector 模拟实现十问十答 —— 从三指针到迭代器失效
c++·后端·面试·stl·vector