当前位置: 首页 > news >正文

C++线程、并发、并行

 【欢迎关注编码小哥,学习更多实用的编程方法和技巧】

一、线程、并发和并行的概念

1、线程定义:

  • 程序执行的最小单元
  • 轻量级的进程
  • 共享同一进程的内存空间

特征:

  • 独立的执行路径
  • 共享进程资源
  • 上下文切换开销较小

类型:

    用户线程

    内核线程

    协程

2、并发定义:

  • 多个任务在同一时间段内交替执行
  • 宏观同时进行,微观交替

特点:

  • 单核CPU也可实现
  • 通过时间片轮转
  • 提高系统响应性
  • 资源利用率提升

实现方式:

    进程间并发

    线程间并发

    协程并发

3、并行定义:

  • 多个任务同时执行
  • 物理上同时运行

特点:

  • 多核/多处理器
  • 真正同时执行
  • 性能显著提升

实现方式:

  • 多核处理
  • 分布式计算
  • GPU并行计算

4、并发 vs 并行

并发:

时间片交替执行
单核CPU
看似同时运行

A    B    C
--|--|--|

并行:

真正同时执行
多核CPU
实际同时运行

A B C
-----

5、并发编程模型

同步模型:

  • 阻塞
  • 非阻塞
  • 同步
  • 异步

通信模型:

    共享内存

    消息传递

    Actor模型

    CSP模型

6、并发编程挑战

常见问题:

  • 竞争条件
  • 死锁
  • 资源争用
  • 线程安全

解决策略:

    互斥锁

    信号量

    原子操作

    无锁编程

7、代码示例

并发示例:

// 并发执行
void concurrentTask() {std::thread t1([]{ // 任务A });std::thread t2([]{ // 任务B });t1.join();t2.join();
}

并行示例:

// 并行计算
void parallelCompute(std::vector<int>& data) {// 使用并行算法std::for_each(std::execution::par,  // 并行执行data.begin(), data.end(), [](int& value) {value *= 2;  // 并行处理每个元素});
}

 8、并发级别

    进程级并发

    线程级并发

    指令级并行

    数据级并行

9、应用场景

适合并发/并行:

    科学计算

    图形渲染

    大数据处理

    网络服务器

    实时系统

10、性能考虑

性能影响因素:

  • 任务granularity
  • 通信开销
  • 同步机制
  • 硬件配置

优化策略:

  • 最小化锁竞争
  • 减少上下文切换
  • 负载均衡
  • 选择合适并发粒度
  • 现代C++并发支持

标准库支持:

  • <thread>
  • <mutex>
  • <condition_variable>
  • <future>
  • <atomic>

选择依据:

  • 任务特性
  • 硬件配置
  • 性能需求
  • 复杂度

建议:

  • 优先考虑并发
  • 评估并行收益
  • 使用高级抽象
  • 谨慎设计

 二、代码实践

1、函数指针创建线程

#include <iostream>
#include <thread>// 普通函数
void threadFunction(int param) {std::cout << "Thread with param: " << param << std::endl;
}int main() {// 使用函数指针创建线程std::thread t1(threadFunction, 42);t1.join();return 0;
}

2、多种函数指针类型

// 不同签名的函数指针
void simpleFunction() {std::cout << "Simple function" << std::endl;
}void paramFunction(int x, double y) {std::cout << "Params: " << x << ", " << y << std::endl;
}int main() {// 无参函数std::thread t1(simpleFunction);// 多参数函数std::thread t2(paramFunction, 10, 3.14);t1.join();t2.join();
}

3、函数指针与引用传递

void referenceFunction(int& value) {value *= 2;
}int main() {int x = 5;// 使用std::ref传递引用std::thread t(referenceFunction, std::ref(x));t.join();std::cout << "Modified x: " << x << std::endl; // 输出10
}

4、类成员函数线程

class Worker {
public:void memberFunction(int param) {std::cout << "Member function: " << param << std::endl;}static void staticMemberFunction(int param) {std::cout << "Static member function: " << param << std::endl;}
};int main() {Worker worker;// 成员函数线程std::thread t1(&Worker::memberFunction, &worker, 100);// 静态成员函数线程std::thread t2(Worker::staticMemberFunction, 200);t1.join();t2.join();
}

5、函数指针与Lambda结合

int main() {// 使用函数指针类型的Lambdaauto lambdaFunc = [](int x) {std::cout << "Lambda thread: " << x << std::endl;};std::thread t(lambdaFunc, 42);t.join();// 动态函数指针typedef void (*FuncPtr)(int);FuncPtr ptr = lambdaFunc;std::thread t2(ptr, 100);t2.join();
}

 6、高级函数指针线程池

#include <vector>
#include <functional>
#include <mutex>class ThreadPool {
private:std::vector<std::thread> threads;std::mutex mutex;public:// 使用函数指针创建线程void addThread(void (*func)(int), int param) {std::lock_guard<std::mutex> lock(mutex);threads.emplace_back(func, param);}// 使用std::function更灵活void addThreadFunc(std::function<void()> func) {std::lock_guard<std::mutex> lock(mutex);threads.emplace_back(func);}void joinAll() {for (auto& t : threads) {if (t.joinable()) {t.join();}}}
};// 示例函数
void workerFunc(int id) {std::cout << "Worker " << id << " running" << std::endl;
}int main() {ThreadPool pool;// 使用函数指针创建线程pool.addThread(workerFunc, 1);pool.addThread(workerFunc, 2);// 使用Lambdapool.addThreadFunc([]() {std::cout << "Lambda thread" << std::endl;});pool.joinAll();
}

 7、安全的函数指针线程管理

class SafeThread {
private:std::unique_ptr<std::thread> thread;std::atomic<bool> stop{false};public:template<typename Func, typename... Args>void start(Func&& func, Args&&... args) {// 确保之前的线程已结束if (thread && thread->joinable()) {thread->join();}// 创建新线程thread = std::make_unique<std::thread>(std::forward<Func>(func), std::forward<Args>(args)...);}void stop() {stop = true;if (thread && thread->joinable()) {thread->join();}}~SafeThread() {stop();}
};

 8、注意事项

  • 避免悬空指针
  • 使用std::ref传递引用
  • 注意生命周期管理
  • 使用智能指针管理资源
  • 考虑线程安全

9、性能建议

  • 尽量减少线程创建开销
  • 使用线程池
  • 避免频繁创建和销毁线程
  • 选择合适的线程数

10、错误处理

try {std::thread t(threadFunction);t.join();
} catch (const std::system_error& e) {std::cerr << "Thread error: " << e.what() << std::endl;
}


http://www.mrgr.cn/news/81715.html

相关文章:

  • 文字显示省略号
  • 深入HDFS——联邦(Federation)
  • Tensor 基本操作1 | PyTorch 深度学习实战
  • C#项目生成时提示缺少引用
  • 计算机网络 (44)电子邮件
  • 接上一主题,实现QtByteArray任意进制字符串转为十进制数
  • 【Leetcode 热题 100】46. 全排列
  • 雷电模拟器安装LSPosed
  • 强化学习基础之贝尔曼期望方程
  • -0.4375 IEEE754表示
  • Python+Django 技术实现自动化漏洞扫描系统开发
  • 【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
  • Python数据可视化小项目
  • 麒麟操作系统服务架构保姆级教程(六)部署PHP环境
  • Prometheus 专栏 —— Prometheus入门介绍
  • 影视仓最新接口+内置本包方法的研究(2024.12.27)
  • MacOS安装Xcode(非App Store)
  • STM32F103RCT6学习之二:GPIO开发
  • 使用 IDE生成 Java Doc
  • 使用 Three.js 创建圣诞树场景
  • Linux 搭建 nginx+keepalived (主备+双主模式) 高可用 | Nginx反向代理
  • Layui 新增销售单 其中一种 编写逻辑和打开方式
  • linux 中文输入法设置的宏观思路 (****)
  • 数据处理之数据规约
  • 文本数据处理
  • 了解智能运维