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

打印 上一主题 下一主题

主题 837|帖子 837|积分 2511

多线程底子

一、C++多线程底子


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

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

二、核心函数详解

1. std::thread()

  1. // 创建线程的三种方式
  2. void func1();
  3. void func2(int num);
  4. // 方式1:普通函数
  5. std::thread t1(func1);
  6. // 方式2:带参数的函数
  7. std::thread t2(func2, 42);
  8. // 方式3:Lambda表达式
  9. std::thread t3([](){
  10.     std::cout << "Lambda thread" << std::endl;
  11. });
复制代码
特性


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

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


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

  1. if(t.joinable()) {
  2.     t.join(); // 或t.detach()
  3. }
复制代码
判定条件


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

  1. std::thread t(func);
  2. t.detach(); // 分离线程
复制代码
特点


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

  1. #include <iostream>
  2. #include <thread>
  3. void print_num(int num) {
  4.     std::cout << "Number: " << num << std::endl;
  5. }
  6. int main() {
  7.     std::thread worker(print_num, 42);
  8.    
  9.     if(worker.joinable()) {
  10.         worker.join(); // 或detach()
  11.     }
  12.    
  13.     return 0;
  14. }
复制代码

线程函数中的数据未界说的错误

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

通报临时变量,临时变量在thread函数竣事后销毁,没有通报到func里,导致未界说错误
  1. #include<iostream>
  2. #include<thread>
  3. void func(int& x) {
  4.         x += 1;
  5. }
  6. int main() {
  7.         std::thread t(func, 1); //传递临时变量,临时变量在thread函数结束后销毁,没有传递到func里,导致未定义错误
  8.         t.join();
  9.         return 0;
  10. }
复制代码
办理方法:创建一个持久变量
  1. #include<iostream>
  2. #include<thread>
  3. void func(int& x) {
  4.         x += 1;
  5.         std::cout << x << " ";
  6. }
  7. int main() {
  8.         int x = 1; //将变量复制到一个持久的对象
  9.         std::thread t(func, std::ref(x));//将变量的引用传递给线程
  10.         t.join();
  11.         return 0;
  12. }
复制代码
2.通报指针或引用指向局部变量的问题

test函数实验竣事,a立刻开释,无法继续传进线程中的func函数中
  1. #include <iostream>
  2. #include<thread>
  3. std::thread t;
  4. void func(int& x) {
  5.         x += 1;
  6. }
  7. void test() {
  8.         int a = 1;
  9.         t = std::thread(func, std::ref(a));
  10. }
  11. int main()
  12. {
  13.         test();
  14.         t.join();
  15.         return 0;
  16. }
复制代码
办理办法,把a 放到表面,a 变成不停可以被取到的全局变量
  1. #include <iostream>
  2. #include<thread>
  3. std::thread t;
  4. int a = 1;
  5. void func(int& x) {
  6.         x += 1;
  7. }
  8. void test() {
  9.        
  10.         t = std::thread(func, std::ref(a));
  11. }
  12. int main()
  13. {
  14.         test();
  15.         t.join();
  16.         return 0;
  17. }
复制代码
3. 通报指针或引用指向已开释的内存的问题

指针在传进去之前delete,导致传进去的是空指针(不指向1)
  1. #include<iostream>
  2. #include<thread>
  3. std::thread t;
  4. void func(int* x) {
  5.         std::cout << *x << std::endl;
  6. }
  7. int main() {
  8.         int* ptr = new int(1);
  9.         std::thread t(func, ptr);
  10.         delete ptr;
  11.         t.join();
  12.         return 0;
  13. }
复制代码
办理办法
取消提前开释即可或利用智能指针
4. 类成员函数作为入口函数,类对象被提前开释

  1. #include<iostream>
  2. #include<thread>
  3. #include<Windows.h>
  4. class A {
  5. public:
  6.         void func() {
  7.                 Sleep(1000);
  8.                 std::cout << "6" << std::endl;
  9.         }
  10. };
  11. int main() {
  12.         A *a;
  13.         std::thread t(&A::func, a);
  14.         delete a;
  15.        
  16.         t.join();
  17. }
复制代码
办理办法:利用智能指针
  1. #include<iostream>
  2. #include<thread>
  3. #include<Windows.h>
  4. class A {
  5. public:
  6.         void func() {
  7.                 Sleep(1000);
  8.                 std::cout << "6" << std::endl;
  9.         }
  10. };
  11. int main() {
  12.         std::shared_ptr<A> a = std::make_shared<A>();//使用智能指针地址一直有效,不会出现提前释放的问题
  13.         std::thread t(&A::func, a);
  14.        
  15.         t.join();
  16. }
复制代码
5.入口函数为类的私有成员函数

  1. #include<iostream>
  2. #include<thread>
  3. #include<Windows.h>
  4. class A {
  5. private:
  6.        
  7.         void func() {
  8.                 Sleep(1000);
  9.                 std::cout << "6" << std::endl;
  10.         }
  11. };
  12. void thread_func() {
  13.         std::shared_ptr<A> a = std::make_shared<A>();
  14.         std::thread t(&A::func, a);
  15.         t.join();
  16. }
  17. int main() {
  18.        
  19.         thread_func();
  20. }
复制代码
办理办法:利用友元函数
  1. #include<iostream>
  2. #include<thread>
  3. #include<Windows.h>
  4. class A {
  5. private:
  6.         friend void thread_func();
  7.         void func() {
  8.                 Sleep(1000);
  9.                 std::cout << "6" << std::endl;
  10.         }
  11. };
  12. void thread_func() {
  13.         std::shared_ptr<A> a = std::make_shared<A>();
  14.         std::thread t(&A::func, a);
  15.         t.join();
  16. }
  17. int main() {
  18.        
  19.         thread_func();
  20. }
复制代码
朝饮花上露,夜卧松下风。
云英化为水,光采与我同。 —王昌龄

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表