球面无盲区多线程编程C++(天阶功法)
(助你金丹、元婴一念而至;洞虚、破妄唾手可得;化神、大乘扶摇直上…未完待续!)
一、多线程基础概念
1. 线程与进程
- 进程:操作系统资源分配的基本单位,拥有独立内存空间
- 线程:进程内的执行单元,共享进程内存,切换开销小
- 并发 vs 并行:
- 并发:交替执行(单核)
- 并行:同时执行(多核)
2. C++多线程支持
- C++11开始原生支持多线程(
<thread>头文件) - 替代方案:POSIX线程(pthread)、WinAPI线程
二、线程基本操作
1. 创建线程
#include <iostream>
#include <thread>
void task(int id) {
std::cout << "Thread " << id << " running\n";
}
int main() {
std::thread t1(task, 1); // 创建线程并执行
std::thread t2(task, 2);
t1.join(); // 等待线程结束
t2.join();
}
2. 线程参数传递
- 值传递:默认方式(复制参数)
- 引用传递:需使用
std::ref
void modify(int& x) { x *= 2; }
int main() {
int value = 5;
std::thread t(modify, std::ref(value));
t.join();
std::cout << value; // 输出10
}
3. 线程管理
- join():阻塞等待线程结束
- detach():分离线程(失去控制权,慎用!)
- 线程ID:
std::this_thread::get_id()
三、线程同步机制
1. 互斥锁(Mutex)
#include <mutex>
std::mutex mtx;
int shared_data = 0;
void increment() {
for (int i = 0; i < 100000; ++i) {
mtx.lock();
++shared_data;
mtx.unlock();
}
}
// 更安全的RAII方式
void safe_increment() {
for (int i = 0; i < 100000; ++i) {
std::lock_guard<std::mutex> lock(mtx);
++shared_data;
}
}
2. 条件变量(Condition Variable)
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void producer() {
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
}
void consumer() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return ready; }); // 自动释放锁并等待
std::cout << "Data ready!\n";
}
3. 原子操作(Atomic)
#include <atomic>
std::atomic<int> counter(0); // 无需锁的线程安全操作
void atomic_increment() {
for (int i = 0; i < 100000; ++i) {
++counter; // 原子操作
}
}
四、高级同步工具
1. 读写锁(C++17)
#include <shared_mutex>
std::shared_mutex rw_mutex;
int data = 0;
// 写操作
void writer() {
std::unique_lock lock(rw_mutex); // 排他锁
data = 42;
}
// 读操作
void reader() {
std::shared_lock lock(rw_mutex); // 共享锁
std::cout << data;
}
2. 信号量(C++20)
#include <semaphore>
std::counting_semaphore<10> sem(3); // 最大计数3
void worker() {
sem.acquire();
// 临界区操作
sem.release();
}
五、异步编程模型
1. std::async与std::future
#include <future>
int compute(int x) { return x * x; }
int main() {
std::future<int> fut = std::async(compute, 5);
std::cout << "Result: " << fut.get(); // 阻塞获取结果
}
2. std::promise与std::future
void task(std::promise<int> prom) {
prom.set_value(42); // 设置结果
}
int main() {
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread t(task, std::move(prom));
t.detach();
std::cout << "Result: " << fut.get();
}
六、线程安全设计原则
- RAII管理资源
- 使用
std::lock_guard/std::unique_lock自动管理锁
- 使用
- 避免数据竞争
- 共享数据必须通过同步机制访问
- 死锁预防
- 按固定顺序获取锁
- 使用
std::scoped_lock(C++17)自动解决锁顺序
- 最小化锁粒度
- 仅保护必要的数据
- 优先使用原子操作
- 适用于简单状态的同步
七、C++20新特性
1. std::jthread(可联合线程)
std::jthread worker([](std::stop_token token) {
while(!token.stop_requested()) {
// 周期性任务
}
});
worker.request_stop(); // 自动join
2. 停止令牌(Stop Token)
void worker(std::stop_token token) {
while(!token.stop_requested()) {
// 可中断的任务循环
}
}
八、性能注意事项
- 避免虚假共享(False Sharing)
- 将频繁访问的独立数据放置在不同缓存行
- 限制线程数量
- 通常为CPU核心数的1-2倍
- 使用无锁数据结构
- 适用于高并发场景
- 减少锁竞争
- 使用细粒度锁或读写锁
九、调试与测试工具
-
Thread Sanitizer(TSan)
g++ -fsanitize=thread -g program.cpp -
Valgrind Helgrind
-
静态分析工具
- Clang Thread Safety Analysis
void foo() __attribute__((require_capability(mutex)));
十、综合示例:生产者-消费者模型
#include <queue>
#include <mutex>
#include <condition_variable>
template<typename T>
class SafeQueue {
public:
void push(T value) {
std::lock_guard lock(mtx);
q.push(std::move(value));
cv.notify_one();
}
T pop() {
std::unique_lock lock(mtx);
cv.wait(lock, [this]{ return !q.empty(); });
T val = std::move(q.front());
q.pop();
return val;
}
private:
std::queue<T> q;
std::mutex mtx;
std::condition_variable cv;
};
void producer(SafeQueue<int>& q) {
for(int i=0; i<10; ++i) q.push(i);
}
void consumer(SafeQueue<int>& q) {
for(int i=0; i<10; ++i) {
int val = q.pop();
std::cout << "Got: " << val << "\n";
}
}
int main() {
SafeQueue<int> queue;
std::jthread p(producer, std::ref(queue));
std::jthread c(consumer, std::ref(queue));
}
总结
- 基础操作:掌握
std::thread的创建、参数传递和生命周期管理 - 同步机制:理解互斥锁、条件变量、原子操作的使用场景
- 高级模式:熟练使用线程池、异步任务和现代线程管理工具
- 性能优化:注重减少锁竞争、避免虚假共享等关键问题
- 现代特性:关注C++20引入的
jthread和停止令牌
通过合理运用这些技术,可以构建高效、安全的多线程程序,充分发挥现代多核处理器的性能潜力。

93

被折叠的 条评论
为什么被折叠?



