c++:thread(线程)

1.基本使用

1.1创建线程

join()函数用于:主程序等待子线程执行完毕之后再继续

cpp 复制代码
#include <iostream>
#include <thread>

void printHello()
{
    std::cout << "hello world" << std::endl;
}

int main()
{
    // 1.创建线程
    std::thread thread1(printHello);
    thread1.join();
    return 0;
}

1.2给子线程传递参数

cpp 复制代码
#include <iostream>
#include <thread>

void printHello(std::string msg)
{
    std::cout << msg << std::endl;
}

int main()
{
    // 1.创建线程
    std::thread thread1(printHello, "hello world");
    thread1.join();
    return 0;
}

1.3通过isJoin来判断是否可以join

cpp 复制代码
#include <iostream>
#include <thread>

void printHello(std::string msg)
{
    std::cout << msg << std::endl;
}

int main()
{
    // 1.创建线程
    std::thread thread1(printHello, "hello world");
    bool isJoin = thread1.joinable();
    if (isJoin)
    {
        thread1.join();
    }

    return 0;
}

2.数据定义

2.1普通变量

虽然这样不会报错,但好像没什么意义,执行完线程的操作之后也得不到我想要的值

cpp 复制代码
#include <iostream>
#include <thread>

void fool(int a)
{
    a += 1;
}

int main()
{
    int a = 1;
    std::thread t(fool, a);
    t.join();
    std::cout << a << std::endl;
}

2.2使用引用

在线程中添加了一个int& a,这样虽然理论上可以让a的值加一,再主线程中也能获取到,但会出现报错

cpp 复制代码
#include <iostream>
#include <thread>

void fool(int &a)
{
    a += 1;
}

int main()
{
    int a = 1;
    std::thread t(fool, a);
    t.join();
    std::cout << a << std::endl;
}

引用是一个右值,而我传递进去的int a,这个a是一个变量,是左值,这就不合法。

使用std::ref(a)来传递a的引用

cpp 复制代码
#include <iostream>
#include <thread>

void fool(int &a)
{
    a += 1;
}

int main()
{
    int a = 1;
    std::thread t(fool, std::ref(a));//使用std::ref来传递a的引用
    t.join();
    std::cout << a << std::endl;
}

2.3指针

为了避免指针被delete,而导致访问时造成悬空指针,我们一般使用智能指针,在程序运行结束之后,让他自己自动回收

2.3.1这是使用unique_ptr遇到问题

unique_ptr是独占指针,在主函数中创建了一个智能指针,指向a,但要在子线程函数fool中访问就不行,因为这是独占指针

cpp 复制代码
#include <iostream>
#include <thread>
#include <memory>

class A
{
public:
    void fool()
    {
        std::cout << "Hello" << std::endl;
    }
};
int main()
{
    std::unique_ptr<A> a = std::make_unique<A>();
    std::thread t(&A::fool, a);
    t.join();
}

虽然可以通过lambda表达式获取到类对象a的引用,来访问他所管理的对象

cpp 复制代码
#include <iostream>
#include <thread>
#include <memory>

class A
{
public:
    void fool()
    {
        std::cout << "Hello" << std::endl;
    }
};
int main()
{
    std::unique_ptr<A> a = std::make_unique<A>();
    std::thread t([&a]()
                  { a->fool(); });
    t.join();
}

这里我们也可以使用shared_ptr(共享指针)来进行操作

cpp 复制代码
#include <iostream>
#include <thread>
#include <memory>

class A
{
public:
    void fool()
    {
        std::cout << "Hello" << std::endl;
    }
};
int main()
{
    std::shared_ptr<A> a = std::make_shared<A>();//显性调用
    //std::shared_ptr<A> a(new A); 隐式调用
    std::thread t(&A::fool, a);
    t.join();
}

2.3.2另外这里的std::thread t(&A::fool, a);为什么要用&A::fool

我们在这里使用thread函数中,其中第一个参数是需要调用的子线程函数,需要传递的是函数的地址。

对于普通函数或静态成员函数,你可以直接使用函数名来获取它们的地址。但是,对于非静态成员函数,有一个隐式this参数,需要使用&ClassName::FunctionName的语法来获取成员函数的地址,这里的&是必要的,因为它表示你正在获取一个指向成员函数的指针,而不是调用该函数。

其实对于普通函数,在thread中想要调用该函数是也可以加&,例如上面的thread(&fool);因为函数名就是指向该函数的指针。

2.3.3把这句代码再解析一遍

std::thread t(&A::fool, a);

&A::fool:这是一个指向A类成员函数的指针,指向A类的fool成员函数。这个指针表明我们想要在线程中执行的函数是A类的fool成员函数。

a:这个参数是指向A类型对象的指针,用于作为fool成员函数的调用者。

相关推荐
Cc.Y2 小时前
Java零基础入门:字符串深度掌握——从基础API到StringBuilder性能优化
java·开发语言·性能优化
java资料站6 小时前
十一、评估测试
开发语言·人工智能·python
左手の明天7 小时前
SLIP 协议封装与解析详解:原理、C 代码与实战案例
linux·c语言·开发语言·c++
海上小飞龙7 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
青少儿编程课堂7 小时前
后缀自动机解析:本质不同子串与最长重复片段统计
c++·python·算法·bfs·信息学竞赛
朝朝辞暮i7 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
狗凯之家源码网7 小时前
淘客口令落地页生成器 PHP 版深度评测
开发语言·php
画绛集美术7 小时前
本地化部署LLM用于美术史问答:一间美术教室的实践记录
开发语言·php
八解毒剂8 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理
乐迪信息8 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉