std::thread用于创建线程执行函数,std::mutex配合std::lock_guard保护共享数据防止竞争,确保多线程程序安全高效运行。

在C++中使用多线程,std::thread 和 std::mutex 是最基础且关键的工具。它们定义在
1. 创建线程:std::thread 的基本用法
std::thread 用于启动一个新线程执行函数。你可以传入普通函数、lambda表达式或仿函数(functor)。
示例:
#include#include void say_hello() { std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl; } int main() { std::thread t(say_hello); // 启动线程 t.join(); // 等待线程结束 return 0; }
注意:join() 表示主线程等待子线程执行完毕。如果不调用 join() 或 detach(),程序终止时会调用 std::terminate()。
立即学习“C++免费学习笔记(深入)”;
你也可以传递参数给线程函数:
void print_number(int n) {
std::cout << "Number: " << n << std::endl;
}
std::thread t(print_number, 42);
t.join();
2. 使用互斥锁保护共享数据:std::mutex
当多个线程访问同一变量时,可能出现数据竞争(data race),导致结果不可预测。使用 std::mutex 可以防止这种情况。
例如,两个线程同时对一个全局计数器加1:
#include#include #include int counter = 0; std::mutex mtx; // 定义互斥锁 void increment() { for (int i = 0; i < 100000; ++i) { mtx.lock(); // 加锁 ++counter; // 安全修改共享数据 mtx.unlock(); // 解锁 } } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Final counter value: " << counter << std::endl; return 0; }
上面代码中,每次修改 counter 前都先获取锁,避免两个线程同时写入。
3. 更安全的锁管理:std::lock\_guard
手动调用 lock() 和 unlock() 容易出错,比如忘记解锁或异常导致跳过 unlock。推荐使用 std::lock_guard 实现 RAII(资源获取即初始化)自动管理锁。
改写上面的 increment 函数:
void increment() {
for (int i = 0; i < 100000; ++i) {
std::lock_guard guard(mtx); // 构造时加锁,析构时自动解锁
++counter;
}
}
即使循环中抛出异常,lock_guard 也会确保释放锁,避免死锁。
4. 常见使用场景与注意事项
- 每个需要同步的共享资源应配一个 mutex,不要多个资源共用一个锁,否则降低并发效率。
- 避免死锁:如果必须使用多个锁,始终按相同顺序加锁。
- 线程函数尽量不要直接操作全局变量,可通过参数传递数据。
- 考虑使用 std::atomic
替代 mutex 用于简单类型(如计数器),性能更高。
基本上就这些。掌握 std::thread 启动线程,配合 std::mutex 和 std::lock_guard 保护共享资源,是C++多线程编程的基础。实际开发中还可结合 std::condition_variable 实现线程通信,但那是进阶内容了。











