c++ 多线程(一)

c++ 多线程

一、基本概念

全局函数可以作为std::thread的构造函数参数,创建新线程时会自动调用该函数。

  • 函数可以是普通函数、静态函数、lambda表达式
  • 线程启动时立即执行该函数
  • 函数执行完毕,线程自动结束

二、基本用法

示例1:最简单的全局函数

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

// 全局函数定义
void simpleTask() {
    std::cout << "线程ID: " << std::this_thread::get_id() 
              << " 正在执行简单任务" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "任务完成" << std::endl;
}

int main() {
    std::cout << "主线程ID: " << std::this_thread::get_id() << std::endl;
    
    // 创建线程,传入全局函数指针
    std::thread t(simpleTask);
    
    // 等待线程完成
    t.join();
    
    return 0;
}

三、带参数的全局函数

示例2:传递参数给线程函数

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

// 带参数的全局函数
void printMessage(const std::string& message, int count) {
    for (int i = 0; i < count; ++i) {
        std::cout << "消息[" << i << "]: " << message 
                  << " (线程ID: " << std::this_thread::get_id() << ")" 
                  << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

int main() {
    // 创建线程时传递参数
    std::thread t1(printMessage, "Hello, Thread!", 3);
    std::thread t2(printMessage, "另一个线程", 5);
    
    t1.join();
    t2.join();
    
    return 0;
}

四、不同类型的全局函数

示例3:静态函数

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

class MyClass {
public:
    static void staticTask(int value) {
        std::cout << "静态函数,值: " << value 
                  << " 线程ID: " << std::this_thread::get_id() 
                  << std::endl;
    }
};

// 普通全局函数
void globalTask(const char* name) {
    std::cout << "全局函数: " << name << std::endl;
}

int main() {
    // 使用静态函数作为线程入口
    std::thread t1(MyClass::staticTask, 42);
    
    // 使用普通全局函数
    std::thread t2(globalTask, "测试线程");
    
    // 使用函数指针
    void (*funcPtr)(const char*) = globalTask;
    std::thread t3(funcPtr, "函数指针");
    
    t1.join();
    t2.join();
    t3.join();
    
    return 0;
}

五、传递引用和指针参数

示例4:传递引用参数

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

// 修改共享数据的全局函数
void processVector(std::vector<int>& vec, int multiplier) {
    std::cout << "处理向量,大小: " << vec.size() 
              << " 线程ID: " << std::this_thread::get_id() 
              << std::endl;
    
    // 修改向量元素
    for (auto& num : vec) {
        num *= multiplier;
    }
}

// 传递指针
void processArray(int* arr, int size) {
    std::cout << "处理数组,大小: " << size << std::endl;
    for (int i = 0; i < size; ++i) {
        arr[i] += 10;
    }
}

int main() {
    // 示例1:传递引用(需要使用std::ref包装)
    std::vector<int> data = {1, 2, 3, 4, 5};
    
    std::thread t1(processVector, std::ref(data), 2);
    t1.join();
    
    std::cout << "处理后的向量: ";
    for (int num : data) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 示例2:传递指针
    int array[5] = {10, 20, 30, 40, 50};
    std::thread t2(processArray, array, 5);
    t2.join();
    
    std::cout << "处理后的数组: ";
    for (int i = 0; i < 5; ++i) {
        std::cout << array[i] << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

六、返回值的处理

示例5:使用future获取返回值

cpp 复制代码
#include <iostream>
#include <thread>
#include <future>
#include <numeric>
#include <vector>

// 计算向量和的全局函数
int calculateSum(const std::vector<int>& vec) {
    std::cout << "计算线程ID: " << std::this_thread::get_id() << std::endl;
    
    // 模拟耗时计算
    std::this_thread::sleep_for(std::chrono::seconds(1));
    
    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    return sum;
}

// 返回多个值的函数
std::pair<int, double> calculateStats(const std::vector<int>& vec) {
    if (vec.empty()) return {0, 0.0};
    
    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    double avg = static_cast<double>(sum) / vec.size();
    
    return {sum, avg};
}

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 方式1:使用std::async(内部使用线程)
    std::future<int> future1 = std::async(std::launch::async, calculateSum, numbers);
    
    // 方式2:使用packaged_task
    std::packaged_task<int(const std::vector<int>&)> task(calculateSum);
    std::future<int> future2 = task.get_future();
    
    std::thread t(std::move(task), numbers);
    
    // 获取结果
    std::cout << "Async结果: " << future1.get() << std::endl;
    std::cout << "Thread结果: " << future2.get() << std::endl;
    
    t.join();
    
    // 获取多个返回值
    std::packaged_task<std::pair<int, double>(const std::vector<int>&)> 
        statsTask(calculateStats);
    std::future<std::pair<int, double>> statsFuture = statsTask.get_future();
    
    std::thread statsThread(std::move(statsTask), numbers);
    
    auto [sum, avg] = statsFuture.get();
    std::cout << "\n统计结果:\n";
    std::cout << "总和: " << sum << "\n平均值: " << avg << std::endl;
    
    statsThread.join();
    
    return 0;
}

七、注意事项

关键注意事项

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

// 1. 线程参数是值传递(除非使用std::ref)
void demonstratePassing(int value, int& ref, const std::string& str) {
    value += 10;  // 修改的是副本
    ref += 10;    // 修改的是原始引用
    std::cout << "字符串: " << str << std::endl;
}

int main() {
    int a = 5;
    int b = 10;
    std::string msg = "测试";
    
    // 正确传递引用
    std::thread t(demonstratePassing, a, std::ref(b), msg);
    t.join();
    
    std::cout << "a = " << a << std::endl;  // 仍然是5
    std::cout << "b = " << b << std::endl;  // 变为20
    
    // 2. 确保参数生命周期
    {
        int* ptr = new int(42);
        std::thread t2([](int* p) {
            std::cout << "值: " << *p << std::endl;
            delete p;  // 在线程内清理
        }, ptr);
        t2.detach();
    }
    
    // 3. 异常安全处理
    try {
        std::thread t3([]() {
            throw std::runtime_error("线程内部异常");
        });
        
        // 确保线程在异常发生时也能被join
        t3.join();
    } catch (const std::exception& e) {
        std::cout << "捕获异常: " << e.what() << std::endl;
    }
    
    return 0;
}

选择建议

  • 简单任务 → 全局函数
  • 需要状态管理 → 函数对象或成员函数
  • 一次性使用 → lambda表达式
  • 需要返回值 → 使用std::future
相关推荐
散峰而望4 小时前
【算法竞赛】C++函数详解:从定义、调用到高级用法
c语言·开发语言·数据结构·c++·算法·github
冷凝雨4 小时前
复数乘法(C & Simulink)
c语言·开发语言·信号处理·simulink·dsp
CoderCodingNo4 小时前
【GESP】C++五级真题(贪心思想考点) luogu-B4071 [GESP202412 五级] 武器强化
开发语言·c++·算法
我有一些感想……4 小时前
An abstract way to solve Luogu P1001
c++·算法·ai·洛谷·mlp
0和1的舞者4 小时前
Spring AOP详解(一)
java·开发语言·前端·spring·aop·面向切面
MoonBit月兔4 小时前
年终 Meetup:走进腾讯|AI 原生编程与 Code Agent 实战交流会
大数据·开发语言·人工智能·腾讯云·moonbit
智航GIS4 小时前
8.2 面向对象
开发语言·python
小小星球之旅4 小时前
CompletableFuture学习
java·开发语言·学习
智者知已应修善业5 小时前
【求等差数列个数/无序获取最大最小次大次小】2024-3-8
c语言·c++·经验分享·笔记·算法
kylezhao20195 小时前
C# 语言基础(变量、数据类型、流程控制、面向对象编程)
开发语言·计算机视觉·c#·visionpro