随着多核处理器的普及,多线程编程已经成为现代C++开发中不可或缺的技能。本文将详细介绍C++多线程编程的核心概念和最佳实践。
1. 线程基础
1.1 创建和管理线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <thread>
#include <iostream>
void worker(int n) {
std::cout << "Thread " << n << " is running\n";
}
int main() {
std::thread t1(worker, 1);
std::thread t2(worker, 2);
t1.join(); // 等待线程完成
t2.join();
return 0;
}
|
1.2 线程传参
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Task {
public:
void execute(std::string& msg, int count) {
for(int i = 0; i < count; ++i) {
std::cout << msg << std::endl;
}
}
};
Task task;
std::string msg = "Hello";
std::thread t(&Task::execute, &task, std::ref(msg), 3);
t.join();
|
2. 互斥量和锁
2.1 基本互斥量使用
1
2
3
4
5
6
7
8
9
|
#include <mutex>
std::mutex mtx;
int shared_data = 0;
void increment() {
std::lock_guard<std::mutex> lock(mtx);
++shared_data;
}
|
2.2 死锁预防
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
std::mutex mutex1, mutex2;
void deadlock_prone() {
// 错误方式:可能导致死锁
std::lock_guard<std::mutex> lock1(mutex1);
std::lock_guard<std::mutex> lock2(mutex2);
}
void deadlock_safe() {
// 正确方式:使用std::lock
std::lock(mutex1, mutex2);
std::lock_guard<std::mutex> lock1(mutex1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mutex2, std::adopt_lock);
}
|
3. 条件变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void producer() {
std::unique_lock<std::mutex> lock(mtx);
ready = true;
cv.notify_one();
}
void consumer() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; });
// 处理数据
}
|
4. 原子操作
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <atomic>
std::atomic<int> counter(0);
void increment() {
++counter; // 原子操作,无需互斥锁
}
void atomic_operations() {
counter.fetch_add(1); // 原子加法
counter.fetch_sub(1); // 原子减法
counter.exchange(5); // 原子交换
}
|
5. 线程池实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
class ThreadPool {
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
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(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>
void enqueue(F&& f) {
{
std::unique_lock<std::mutex> lock(queue_mutex);
tasks.emplace(std::forward<F>(f));
}
condition.notify_one();
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for(std::thread &worker: workers) {
worker.join();
}
}
};
|
6. 异步任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <future>
std::future<int> calculate_async() {
return std::async(std::launch::async, []() {
// 耗时计算
return 42;
});
}
void use_async() {
auto future = calculate_async();
// 做其他工作
int result = future.get(); // 获取结果
}
|
7. 读写锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include <shared_mutex>
class ThreadSafeCounter {
mutable std::shared_mutex mutex_;
int value_ = 0;
public:
// 写操作使用独占锁
void increment() {
std::unique_lock<std::shared_mutex> lock(mutex_);
++value_;
}
// 读操作使用共享锁
int get() const {
std::shared_lock<std::shared_mutex> lock(mutex_);
return value_;
}
};
|
最佳实践建议
- 优先使用高级同步原语(如std::async)而不是直接管理线程
- 使用RAII风格的锁管理(如std::lock_guard)
- 避免使用全局变量存储线程间共享数据
- 合理使用原子操作代替互斥量
- 注意防止死锁和竞态条件
性能优化技巧
- 减少锁的粒度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Optimized {
std::mutex mutex_;
std::vector<int> data_;
public:
void add(int value) {
// 在锁外准备数据
int new_value = process(value);
{
std::lock_guard<std::mutex> lock(mutex_);
data_.push_back(new_value);
}
}
};
|
- 使用无锁数据结构
1
2
3
4
5
6
7
8
9
|
template<typename T>
class LockFreeQueue {
struct Node {
T data;
std::atomic<Node*> next;
};
std::atomic<Node*> head_;
std::atomic<Node*> tail_;
};
|
总结
C++多线程编程是一个复杂但重要的主题。通过合理使用互斥量、条件变量、原子操作等同步原语,我们可以构建高效的并发程序。关键是要理解并发编程的核心概念,遵循最佳实践,并在实践中不断积累经验。