首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++ 并发编程详解与实践

C++ 并发编程详解与实践

原创
作者头像
用户11690575
发布2025-06-06 07:06:47
发布2025-06-06 07:06:47
27600
代码可运行
举报
运行总次数:0
代码可运行

一、引言

随着多核处理器的普及,并发编程成为提升程序性能的关键手段。C++ 自 C++11 标准引入线程支持后,提供了完整的多线程编程库,极大地方便了高性能并发程序的开发。

本篇文章将详细介绍 C++ 并发编程基础、线程管理、同步机制、原子操作、线程池设计及典型并发问题的解决方法,帮助读者掌握实用的并发开发技能。


二、线程的创建与管理

2.1 创建线程

C++11 引入 std::thread,可方便创建线程。

代码语言:javascript
代码运行次数:0
运行
复制
cpp复制编辑#include <thread>
#include <iostream>

void worker(int id) {
    std::cout << "线程 " << id << " 正在运行\n";
}

int main() {
    std::thread t(worker, 1);  // 创建线程
    t.join();                  // 等待线程结束
    return 0;
}

2.2 线程分离与连接

  • join() 等待线程结束,阻塞调用线程。
  • detach() 让线程后台运行,主线程不等待。

2.3 线程的生命周期管理

线程对象销毁前必须调用 join()detach(),否则程序会异常终止。


三、同步机制详解

并发环境中共享数据需要同步防止数据竞争。

3.1 互斥量(Mutex)

代码语言:javascript
代码运行次数:0
运行
复制
cpp复制编辑#include <mutex>
std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    ++counter;
}

lock_guard 是 RAII 风格,确保锁的自动释放。

3.2 读写锁(shared_mutex)

允许多个读线程并发,写线程独占。

代码语言:javascript
代码运行次数:0
运行
复制
cpp复制编辑#include <shared_mutex>
std::shared_mutex rw_mutex;

void read() {
    std::shared_lock<std::shared_mutex> lock(rw_mutex);
    // 读操作
}

void write() {
    std::unique_lock<std::shared_mutex> lock(rw_mutex);
    // 写操作
}

3.3 条件变量(Condition Variable)

用于线程间等待和通知。

代码语言:javascript
代码运行次数:0
运行
复制
cpp复制编辑#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void wait_thread() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return ready; });
    // 继续执行
}

void signal_thread() {
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();
}

四、原子操作与无锁编程

4.1 std::atomic 类型

支持原子读写,避免数据竞争。

代码语言:javascript
代码运行次数:0
运行
复制
cpp复制编辑#include <atomic>
std::atomic<int> count(0);

void increment() {
    count.fetch_add(1, std::memory_order_relaxed);
}

4.2 内存序(Memory Order)

定义操作的可见顺序,常用:

  • memory_order_relaxed — 无同步,仅保证原子性。
  • memory_order_acquire / memory_order_release — 用于同步。
  • memory_order_seq_cst — 最强同步保证。

五、线程池设计与实现

线程池复用线程资源,提高性能。

5.1 简单线程池示例

代码语言:javascript
代码运行次数:0
运行
复制
cpp复制编辑#include <vector>
#include <thread>
#include <queue>
#include <functional>
#include <condition_variable>
#include <atomic>

class ThreadPool {
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;
    std::mutex queue_mutex;
    std::condition_variable condition;
    std::atomic<bool> stop;

public:
    ThreadPool(size_t threads) : stop(false) {
        for (size_t i = 0; i < threads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        this->condition.wait(lock, [this] {
                            return this->stop || !this->tasks.empty();
                        });
                        if (this->stop && this->tasks.empty())
                            return;
                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }
                    task();
                }
            });
        }
    }

    void enqueue(std::function<void()> task) {
        {
            std::lock_guard<std::mutex> lock(queue_mutex);
            tasks.push(std::move(task));
        }
        condition.notify_one();
    }

    ~ThreadPool() {
        stop = true;
        condition.notify_all();
        for (auto &worker : workers) worker.join();
    }
};

六、典型并发问题及解决方案

6.1 死锁

多个线程互相等待对方释放资源。

解决方案:

  • 保持资源请求顺序一致
  • 使用 std::lock 同时锁多个 mutex
  • 避免持有锁时调用可能阻塞的操作

6.2 饥饿与优先级反转

低优先级线程长时间得不到 CPU。

解决方案:

  • 合理设计线程优先级
  • 使用公平锁(fair lock)

6.3 竞态条件(Race Condition)

多个线程读写同一数据导致错误。

解决方案:

  • 使用互斥量保护共享数据
  • 使用原子操作

七、并发设计模式

7.1 生产者-消费者模型

利用条件变量同步任务队列。

7.2 任务划分与结果合并

将大任务拆分并发执行,最后合并结果。


八、并发编程调试技巧

  • 使用 Thread Sanitizer 检测数据竞争
  • 日志打印线程 ID 和时间戳
  • 小步调试,逐步添加并发控制

九、总结

C++ 的并发编程提供了强大灵活的工具,但也带来复杂的同步问题。理解线程管理、同步机制和常见陷阱,是写出高效且安全并发程序的关键。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、引言
  • 二、线程的创建与管理
    • 2.1 创建线程
    • 2.2 线程分离与连接
    • 2.3 线程的生命周期管理
  • 三、同步机制详解
    • 3.1 互斥量(Mutex)
    • 3.2 读写锁(shared_mutex)
    • 3.3 条件变量(Condition Variable)
  • 四、原子操作与无锁编程
    • 4.1 std::atomic 类型
    • 4.2 内存序(Memory Order)
  • 五、线程池设计与实现
    • 5.1 简单线程池示例
  • 六、典型并发问题及解决方案
    • 6.1 死锁
    • 6.2 饥饿与优先级反转
    • 6.3 竞态条件(Race Condition)
  • 七、并发设计模式
    • 7.1 生产者-消费者模型
    • 7.2 任务划分与结果合并
  • 八、并发编程调试技巧
  • 九、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档