线程启动、结束,创建线程多法、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();
相关推荐
MC皮蛋侠客4 小时前
Google Test 单元测试指南
c++·单元测试·google test
2301_809051145 小时前
Linux 网络编程 学习笔记
linux·网络·学习
wanhengidc5 小时前
服务器租用有何优点
运维·服务器·安全·web安全
方也_arkling5 小时前
【Java-Day08】static / final / 枚举
java·开发语言
坤昱5 小时前
cfs调度类深入解刨——最新内核细节分析2
linux·服务器·cfs·cfs调度·eevdf调度·eevdf·kernel 7.1
艾莉丝努力练剑5 小时前
【Linux:文件】Ext系列文件系统进阶
linux·运维·服务器·c++·文件系统·文件io·ext
海市公约5 小时前
Linux核心基础命令与权限管理实战指南
linux·运维·服务器·vim·权限管理·系统监控·命令行
风吹夏回5 小时前
Python 全局异常处理:从“满屏 try-except”到优雅兜底
开发语言·python
Chengbei116 小时前
一站式源码安全检测工具、云安全 / APP / 小程序源码敏感信息递归多层目录扫描AK、JWT、手机号、身份证等敏感信息
java·开发语言·安全·web安全·网络安全·系统安全·安全架构
llz_1126 小时前
web-第一次课后作业
java·开发语言·idea