C++多线程相关应用

一、多线程基础

1. 线程创建与管理

#include <thread>
#include <iostream>

void task(int id) {
   
    std::cout << "Thread " << id << " executing\n";
}

int main() {
   
    std::thread t1(task, 1);  // 创建线程
    std::thread t2([](){
          // Lambda表达式创建线程
        std::cout << "Lambda thread\n";
    });

    t1.join();  // 等待线程结束
    t2.join();

    // detach示例(谨慎使用)
    std::thread t3([]{
    /* 后台任务 */ });
    t3.detach();
}

2. 线程生命周期管理

  • join():阻塞等待线程结束
  • detach():分离线程(失去控制权)
  • RAII包装器:
    class ThreadGuard {
         
      std::thread& t;
    public:
      explicit ThreadGuard(std::thread& t_) : t(t_) {
         }
      ~ThreadGuard() {
         
          if(t.joinable()) {
         
              t.join();  // 或根据需求选择detach
          }
      }
    };

二、互斥量(Mutex)应用

1. 基础锁机制

#include <mutex>

std::mutex mtx;
int shared_data = 0;

void safe_increment() {
   
    std::lock_guard<std::mutex> lock(mtx);  // RAII自动解锁
    ++shared_data;
}

// 递归锁示例
std::recursive_mutex rec_mtx;
void recursive_func(int n) {
   
    std::lock_guard<std::recursive_mutex> lock(rec_mtx);
    if(n > 0) recursive_func(n-1);
}

2. 死锁预防

// 使用std::lock同时锁定多个互斥量
std::mutex mtx1, mtx2;

void safe_process() {
   
    std::unique_lock<std::mutex> lock1(mtx1, std::defer_lock);
    std::unique_lock<std::mutex> lock2(mtx2, std::defer_lock);
    std::lock(lock1, lock2);  // 原子化锁定

    // 临界区操作
}

三、条件变量(Condition Variable)

1. 生产者-消费者模型

#include <queue>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue;

void producer() {
   
    for(int i=0; i<5; ++i) {
   
        {
   
            std::lock_guard<std::mutex> lock(mtx);
            data_queue.push(i);
        }
        cv.notify_one();  // 通知消费者
    }
}

void consumer() {
   
    while(true) {
   
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, []{
    return !data_queue.empty(); }); // 防止虚假唤醒

        int data = data_queue.front();
        data_queue.pop();
        lock.unlock();

        std::cout << "Consumed: " << data << std::endl;
        if(data == 4) break;
    }
}

2. 条件变量使用要点

  • 始终在循环中检查条件
  • 使用notify_all()广播通知多个等待线程
  • 注意通知时机,避免丢失信号

四、原子变量(Atomic)

1. 基础使用

#include <atomic>

std::atomic<int> counter(0);  // 无需锁的线程安全计数器

void atomic_increment() {
   
    for(int i=0; i<1000; ++i) {
   
        counter.fetch_add(1, std::memory_order_relaxed);
    }
}

// 测试代码
std::thread t1(atomic_increment);
std::thread t2(atomic_increment);
t1.join(); t2.join();
std::cout << "Final counter: " << counter << std::endl;  // 正确输出2000

2. 内存序选择

内存序 特性 使用场景
memory_order_relaxed 无顺序保证 计数器等简单操作
memory_order_consume 数据依赖排序 很少使用
memory_order_acquire 加载操作前的访问可见 锁获取
memory_order_release 存储操作后的修改可见 锁释放
memory_order_seq_cst 全局顺序一致(默认) 需要严格顺序的场景

五、综合应用案例

1. 线程池实现

#include <vector>
#include <future>

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

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

                        if(stop && tasks.empty()) return;

                        task = std::move(tasks.front());
                        tasks.pop();
                    }
                    task();
                }
            });
        }
    }

    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
   
        using return_type = decltype(f(args...));

        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );

        std::future<return_type> res = task->get_future();
        {
   
            std::lock_guard<std::mutex> lock(queue_mutex);
            if(stop) throw std::runtime_error("enqueue on stopped ThreadPool");

            tasks.emplace([task](){
    (*task)(); });
        }
        condition.notify_one();
        return res;
    }

    ~ThreadPool() {
   
        {
   
            std::lock_guard<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for(std::thread &worker : workers)
            worker.join();
    }
};

六、性能优化与陷阱

1. 锁粒度控制

// 错误示例:大粒度锁
std::mutex big_lock;
void process_data() {
   
    std::lock_guard<std::mutex> lock(big_lock);  // 锁住整个函数
    // 长时间操作...
}

// 优化:细粒度锁
struct DataPart {
   
    std::mutex mtx;
    int value;
};
DataPart part1, part2;

void process_part(DataPart& part) {
   
    std::lock_guard<std::mutex> lock(part.mtx);
    // 操作单个数据部分
}

2. 虚假唤醒防护

std::condition_variable cv;
bool ready = false;  // 必须的条件判断变量

// 正确写法
cv.wait(lock, []{
    return ready; }); 

// 错误写法(可能虚假唤醒)
while(!ready) cv.wait(lock);

3. 原子操作陷阱

std::atomic<bool> flag(false);
int non_atomic_data = 0;

void thread1() {
   
    non_atomic_data = 42;          // ①
    flag.store(true);              // ②
}

void thread2() {
   
    if(flag.load()) {
                 // ③
        std::cout << non_atomic_data;  // ④ 可能看到0或42
    }
}
// 需要memory_order_release/acquire保证可见性

七、现代C++新特性

1. std::async异步操作

#include <future>

auto future = std::async(std::launch::async, []{
   
    std::this_thread::sleep_for(1s);
    return 42;
});

// 等待结果
std::cout << future.get() << std::endl;

2. 读写锁(C++17)

#include <shared_mutex>

std::shared_mutex rw_mutex;
void reader() {
   
    std::shared_lock lock(rw_mutex);  // 共享锁
    // 读操作...
}

void writer() {
   
    std::unique_lock lock(rw_mutex);  // 独占锁
    // 写操作...
}

八、调试与检测工具

  1. Thread Sanitizer(TSan)

    clang++ -fsanitize=thread -g program.cpp
  2. Mutex死锁检测

    // 使用std::scoped_lock(C++17)
    std::mutex mtx1, mtx2;
    std::scoped_lock lock(mtx1, mtx2);  // 自动死锁避免
  3. 性能分析工具

  • Perf
  • Intel VTune
  • Valgrind的DRD工具
posted @ 2025-11-01 17:15  yijg9998  阅读(3)  评论(0)    收藏  举报