线程启动、结束,创建线程多法、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();
相关推荐
xiaoye-duck2 分钟前
《Linux 网络编程》深入传输层 UDP 协议原理:端口、报文、缓冲区与内核源码解析
linux·网络·udp
lzx_00232 分钟前
C++11(一)
开发语言·c++·算法
好评12434 分钟前
【Linux】数据链路层
linux·运维·网络
天衍四九-38 分钟前
第一章:从 LLM 到 Agent —— DeepSeek Harness 入门
网络·数据库·人工智能·python
Jae den42 分钟前
网络丢包是什么?
网络
未来之窗软件服务1 小时前
计算机二级[英文]-C 字符串移动—东方仙盟
c语言·开发语言·仙盟创梦ide·东方仙盟
Wang's Blog1 小时前
Java框架快速入门: Spring Security+OAuth2之过滤器与过滤器链
java·开发语言·spring
谢尔登1 小时前
01_Java基础速通
java·开发语言
前端炒粉1 小时前
DOM 常用 API 速查表
开发语言·javascript·ecmascript
辻弋2011 小时前
自动检测硬件生成驱动清单、实时监控FPS、120秒性能记录——30+项优化模块化开关,所有改动可精确复原
服务器·windows·游戏引擎·电脑·开源软件