【c++】thread总结

方式1:绑定普通函数(无参数/有参数)

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

// 普通函数(无参数)
void normalFunc() {
    std::cout << "普通无参函数线程\n";
}

// 普通函数(有参数)
void normalFuncWithArgs(int a, std::string b) {
    std::cout << "参数:" << a << ", " << b << "\n";
}

int main() {
    // 无参普通函数
    std::thread t1(normalFunc);
    t1.join(); // 等待线程结束

    // 有参普通函数(参数按值传递,支持多参数)
    std::thread t2(normalFuncWithArgs, 100, "hello");
    t2.join();

    return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

方式2:绑定类成员函数

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

class MQTTManager {
public:
    void connectionLoop() {
        std::cout << "MQTT 连接循环(成员函数线程)\n";
    }

    // 带参数的成员函数
    void loopWithArgs(int timeout) {
        std::cout << "超时时间:" << timeout << "ms\n";
    }
};

int main() {
    MQTTManager mgr;

    // 无参成员函数(必须传 this/实例指针)
    std::thread t1(&MQTTManager::connectionLoop, &mgr);
    t1.join();

    // 带参数的成员函数(参数跟在 this 后)
    std::thread t2(&MQTTManager::loopWithArgs, &mgr, 5000);
    t2.join();

    return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

方式3:绑定lambda表达式

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

int main() {
    std::string msg = "lambda 线程";
    int num = 10;

    // 捕获上下文变量(值捕获/引用捕获)
    std::thread t([msg, &num]() {
        num++; // 引用捕获,修改外部变量
        std::cout << "lambda:" << msg << ",num=" << num << "\n";
    });
    t.join();

    std::cout << "外部 num=" << num << "\n"; // 输出 11
    return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

结果

方式4:绑定函数对象(仿函数)

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

// 函数对象(重载()运算符)
class ThreadFunc {
public:
    void operator()(int x) {
        std::cout << "函数对象:x=" << x << "\n";
    }
};

int main() {
    // 注意:避免最令人头疼的解析(加括号或用统一初始化)
    std::thread t(ThreadFunc(), 20); 
    // 或 std::thread t{ThreadFunc(), 20};
    t.join();
    return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

方式5:分离线程(detach)

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

void detachFunc() {
    for (int i = 0; i < 3; i++) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << "分离线程运行中...\n";
    }
}

int main() {
    std::thread t(detachFunc);
    t.detach(); // 分离线程

    std::cout << "主线程等待 2 秒...\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "主线程退出\n";
    // 分离线程还没跑完 3 次,但主线程退出,线程被终止
    return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

方式6:分离线程(加锁)

cpp 复制代码
#include <atomic>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

class MyClass {
public:
  MyClass() = default;
  MyClass(const MyClass &) = delete;
  MyClass &operator=(const MyClass &) = delete;

  void function1() {
    // 加锁
    std::lock_guard<std::mutex> lock(mt);
    std::cout << "this is function1......" << std::endl;
  }

  void function2(int num, std::string str) {
    // 加锁
    std::lock_guard<std::mutex> lock(mt);
    std::cout << "this is function2......"
              << "num = " << num << ", str = " << str << std::endl;
  }

  void test() {
    if (t1.joinable()) {
      t1.join();
    }
    t1 = std::thread(&MyClass::function1, this);
  }

  void tes2(int num, std::string str) {
    if (t2.joinable()) {
      t2.join();
    }
    t2 = std::thread(&MyClass::function2, this, num, str);
  }

  ~MyClass() {
    std::cout << "this is ~MyClass ......" << std::endl;
    if (t1.joinable()) {
      std::cout << "this is ~t1 ......" << std::endl;
      t1.join();
    }

    if (t2.joinable()) {
      std::cout << "this is ~t2 ......" << std::endl;
      t2.join();
    }
  }

private:
  std::thread t1;
  std::thread t2;
  std::mutex mt;
};

int main() {
  MyClass myClass;
  myClass.test();
  myClass.tes2(10, "hello");

  return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

方式7:分离线程(持续运行)

cpp 复制代码
#include <atomic>
#include <chrono>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

class MyClass {
public:
  MyClass() = default;
  MyClass(const MyClass &) = delete;
  MyClass &operator=(const MyClass &) = delete;

  // 开始
  void start() { isRunnig = true; }

  // 结束
  void stop() {
    isRunnig = false;
    if (t1.joinable()) {
      t1.join();
    }
    if (t2.joinable()) {
      t2.join();
    }
  }

  void function1() {
    while (isRunnig) {
      {
        std::lock_guard<std::mutex> lock(mt);
        std::cout << "this is function1......" << std::endl;
      }

      // 模拟任务耗时
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    // 退出时打印日志
    std::lock_guard<std::mutex> lock(mt);
    std::cout << "function1 exit......" << std::endl;
  }

  void function2(int num, std::string str) {
    while (isRunnig) {
      {
        std::lock_guard<std::mutex> lock(mt);
        std::cout << "this is function2......"
                  << "num = " << num << ", str = " << str << std::endl;
      }
      // 模拟任务耗时
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
    // 退出时打印日志
    std::lock_guard<std::mutex> lock(mt);
    std::cout << "function2 exit......" << std::endl;
  }

  void test() {
    if (t1.joinable()) {
      t1.join();
    }
    // 启动function1的循环线程
    t1 = std::thread(&MyClass::function1, this);
  }

  void tes2(int num, std::string str) {
    if (t2.joinable()) {
      t2.join();
    }
    // 启动function2的循环线程
    t2 = std::thread(&MyClass::function2, this, num, str);
  }

  ~MyClass() {
    std::cout << "this is ~MyClass ......" << std::endl;
    stop();
  }

private:
  std::thread t1;
  std::thread t2;
  std::mutex mt;
  std::atomic<bool> isRunnig{false};
};

int main() {
  MyClass myClass;
  myClass.start();
  myClass.test();
  myClass.tes2(10, "hello");

  std::this_thread::sleep_for(std::chrono::seconds(5));
  myClass.stop();

  return 0;
}

结果

bash 复制代码
g++ test.cpp -lpthread

join和detach的区别

  1. join ():"等待线程干完活再走"
  • 行为 :调用 join() 的线程(比如主线程)会暂停执行,直到目标线程的入口函数执行完毕;

  • 资源:目标线程结束后,其系统资源(栈、内核线程结构体)会被立即回收,线程对象变为 "非可连接" 状态;

  • 核心特点同步阻塞,主线程与子线程强关联,子线程必须执行完,主线程才能继续。

  1. detach ():"线程你自己干,我不管了"
  • 行为 :调用 detach() 后,线程对象与实际执行的线程解绑,子线程变为 "后台线程"(类似 Linux 的守护进程);

  • 资源:子线程的资源由操作系统在其执行完毕后自动回收,主线程无法感知也无法控制;

  • 核心特点异步非阻塞 ,主线程与子线程无关联,主线程退出时,子线程会被操作系统强制终止(即使没执行完)。

选 join () 的场景 选 detach () 的场景
需要等待子线程执行完成(依赖其结果 / 状态) 子线程是 "后台任务"(如日志收集、心跳检测),无需等待结果
子线程访问主线程 / 类的资源(如成员变量) 子线程不依赖主线程资源,且生命周期与程序一致
程序退出前必须完成子线程任务(如文件写入) 子线程可随时被终止(如临时的监控任务)
相关推荐
@小白鸽2 小时前
匿名函数lambda
c++·匿名函数
小鸡脚来咯2 小时前
java泛型详解
java·开发语言
饕餮怪程序猿2 小时前
贪心算法经典应用:活动选择问题(C++实现)
c++·算法·贪心算法
liuyouzhang2 小时前
备忘-国密解密算法
java·开发语言
暗然而日章2 小时前
C++基础:Stanford CS106L学习笔记 15 RAII&智能指针&构建C++工程
c++·笔记·学习
光羽隹衡2 小时前
决策树项目——电信客户流失预测
算法·决策树·机器学习
TL滕2 小时前
从0开始学算法——第二十一天(高级链表操作)
笔记·学习·算法
CoovallyAIHub2 小时前
无人机低空视觉数据集全景解读:从单机感知到具身智能的跨越
深度学习·算法·计算机视觉
学编程就要猛2 小时前
算法:1.移动零
java·算法