线程启动、结束,创建线程多法、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();
相关推荐
上海云盾安全满满11 分钟前
选择接入高防IP后,源机是否还要带有防护
网络·网络协议·tcp/ip
赏金术士36 分钟前
Kotlin 从入门到进阶 之作用域函数 & 优雅写法(五)
android·开发语言·kotlin
openKaka_1 小时前
从 scheduleUpdateOnFiber 到 Root 微任务调度:React 如何把更新交给调度系统
开发语言·前端·javascript
杰 .1 小时前
Linux工具使用
linux·服务器
梦梦代码精1 小时前
《企业开源商城选型:商业闭环、二次开发与成本平衡》
java·开发语言·低代码·开源·github
前进的李工1 小时前
智能Agent实战指南:记忆组件嵌入技巧(记忆)
开发语言·前端·javascript·python·langchain·agent
Gc9umsbL11 小时前
零基础学Linux:21天从“命令小白”到独立部署服务器
linux·运维·服务器
蜡笔小马1 小时前
03.C++设计模式-原型模式
c++·设计模式·原型模式
神仙别闹1 小时前
基于QT(C++)实现线性表的建立、插入、删除、查找等基本操作
java·c++·qt
测试员周周1 小时前
【AI测试功能5】AI功能测试的“黄金数据集“构建指南:从0到1搭建质量评估体系
运维·服务器·开发语言·人工智能·python·功能测试·集成测试