温锦文欧普厨电及净水器总代理 发表于 2025-2-22 13:13:32

thread---基本利用和常见错误

多线程底子

一、C++多线程底子


[*]线程概念:线程是操作体系能够调理的最小实验单元,同一进程内的多个线程共享内存空间
[*]头文件:#include <thread>
[*]线程生命周期:创建->实验->销毁(需显式管理)
[*]注意事项:

[*]线程函数参数建议利用值通报
[*]注意数据竞争问题(需配合互斥锁利用)
[*]主线程退出前必须处理所有子线程

二、核心函数详解

1. std::thread()

// 创建线程的三种方式
void func1();
void func2(int num);

// 方式1:普通函数
std::thread t1(func1);

// 方式2:带参数的函数
std::thread t2(func2, 42);

// 方式3:Lambda表达式
std::thread t3([](){
    std::cout << "Lambda thread" << std::endl;
});
特性:


[*]构造函数立即启动线程
[*]参数自动转发给线程函数
[*]必须处理线程对象(join或detach)
2. join()

std::thread t(func);
t.join(); // 阻塞当前线程,直到t执行完成
特点:


[*]同步线程实验顺序
[*]每个线程对象只能调用一次
[*]调用后线程对象不再关联实际线程
3. joinable()

if(t.joinable()) {
    t.join(); // 或t.detach()
}
判定条件:


[*]线程已被创建(关联实际体系线程),正在进行的线程返回true
[*]尚未被join或detach
4. detach()

std::thread t(func);
t.detach(); // 分离线程
特点:


[*]线程在后台独立运行(保卫线程)
[*]失去对线程的直接控制
[*]必须确保线程函数内的资源有效性
三、利用示例

#include <iostream>
#include <thread>

void print_num(int num) {
    std::cout << "Number: " << num << std::endl;
}

int main() {
    std::thread worker(print_num, 42);
   
    if(worker.joinable()) {
      worker.join(); // 或detach()
    }
   
    return 0;
}
线程函数中的数据未界说的错误

1.临时变量导致的传参错误

通报临时变量,临时变量在thread函数竣事后销毁,没有通报到func里,导致未界说错误
#include<iostream>
#include<thread>
void func(int& x) {
        x += 1;
}
int main() {
        std::thread t(func, 1); //传递临时变量,临时变量在thread函数结束后销毁,没有传递到func里,导致未定义错误
        t.join();
        return 0;
}

办理方法:创建一个持久变量
#include<iostream>
#include<thread>
void func(int& x) {
        x += 1;
        std::cout << x << " ";
}
int main() {
        int x = 1; //将变量复制到一个持久的对象
        std::thread t(func, std::ref(x));//将变量的引用传递给线程
        t.join();
        return 0;
}
2.通报指针或引用指向局部变量的问题

test函数实验竣事,a立刻开释,无法继续传进线程中的func函数中
#include <iostream>
#include<thread>

std::thread t;
void func(int& x) {
        x += 1;
}
void test() {
        int a = 1;
        t = std::thread(func, std::ref(a));
}
int main()
{
        test();
        t.join();
        return 0;
}
办理办法,把a 放到表面,a 变成不停可以被取到的全局变量
#include <iostream>
#include<thread>

std::thread t;
int a = 1;

void func(int& x) {
        x += 1;
}

void test() {
       
        t = std::thread(func, std::ref(a));
}
int main()
{
        test();
        t.join();
        return 0;
}
3. 通报指针或引用指向已开释的内存的问题

指针在传进去之前delete,导致传进去的是空指针(不指向1)
#include<iostream>
#include<thread>

std::thread t;
void func(int* x) {
        std::cout << *x << std::endl;
}

int main() {
        int* ptr = new int(1);
        std::thread t(func, ptr);
        delete ptr;

        t.join();
        return 0;
}
办理办法
取消提前开释即可或利用智能指针
4. 类成员函数作为入口函数,类对象被提前开释

#include<iostream>
#include<thread>
#include<Windows.h>

class A {
public:
        void func() {
                Sleep(1000);
                std::cout << "6" << std::endl;
        }

};

int main() {
        A *a;
        std::thread t(&A::func, a);
        delete a;
       
        t.join();
}

办理办法:利用智能指针
#include<iostream>
#include<thread>
#include<Windows.h>

class A {
public:
        void func() {
                Sleep(1000);
                std::cout << "6" << std::endl;
        }
};

int main() {
        std::shared_ptr<A> a = std::make_shared<A>();//使用智能指针地址一直有效,不会出现提前释放的问题
        std::thread t(&A::func, a);
       
        t.join();
}
5.入口函数为类的私有成员函数

#include<iostream>
#include<thread>
#include<Windows.h>

class A {
private:
       
        void func() {
                Sleep(1000);
                std::cout << "6" << std::endl;
        }
};

void thread_func() {
        std::shared_ptr<A> a = std::make_shared<A>();
        std::thread t(&A::func, a);
        t.join();
}

int main() {
       
        thread_func();
}
办理办法:利用友元函数
#include<iostream>
#include<thread>
#include<Windows.h>

class A {
private:
        friend void thread_func();
        void func() {
                Sleep(1000);
                std::cout << "6" << std::endl;
        }
};

void thread_func() {
        std::shared_ptr<A> a = std::make_shared<A>();
        std::thread t(&A::func, a);
        t.join();
}

int main() {
       
        thread_func();
}

朝饮花上露,夜卧松下风。
云英化为水,光采与我同。 —王昌龄

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: thread---基本利用和常见错误