C++11所支持的线程库
C++11 之前,在 C++ 中进行多线程编程通常需要依赖平台特定的库,如 Windows 下的 Windows API,Linux 下的线程库(pthread)。不同平台的接口差异很大,代码移植性差。C++11 引入了 <thread> 等相关头文件组成的线程库
线程的创建与启动
通过std::thread类来创建和管理线程。std::thread 的构造函数接受一个可调用对象(函数、函数对象、lambda 表达式等)作为参数,线程启动后会执行这个可调用对象。
基本用法
#include <iostream>
#include <thread>
// 1. 普通函数作为线程函数
void test() {
std::cout << "test -> thread ID: "
<< std::this_thread::get_id() << std::endl;
}
// 2. 仿函数作为线程函数
class functor {
public:
void operator()() {
std::cout << "functor -> thread ID: "
<< std::this_thread::get_id() << std::endl;
}
};
// 3. Lambda 表达式作为线程函数
auto Lambda = []() {
std::cout << "lambda -> thread ID: "
<< std::this_thread::get_id() << std::endl;
};
int main() {
std::cout << "main thread ID: " << std::this_thread::get_id() << std::endl;
// 创建线程的多种方式
std::thread t1(test); // 函数指针
std::thread t2{functor()}; // 仿函数
std::thread t3(Lambda); // lambda
std::thread t4([]() { // 直接 lambda
std::cout << "lambda" << std::endl;
});
// 等待所有线程完成
t1.join();
t2.join();
t3.join();
t4.join();
std::cout << "all threads completed!" << std::endl;
return 0;
}
注:以 线程t1 简单说明一下
std::thread t1(test); 创建了一个新线程t1,该线程会执行 test 函数。
std::this_thread::get_id() 用于获取当前线程的唯一标识符。
t1.join(); 会阻塞主线程,直到子线程 t1 执行完毕。
带参数的线程函数
可以向线程执行的函数传递参数,传递的参数会被拷贝到新线程的执行环境里面
#include <iostream>
#include <thread>
void printNumber(int num) {
std::cout << "thread ID " << std::this_thread::get_id() << std::endl;
std::cout << " print number: " << num << std::endl;
}
int main() {
int number = 9;
// 向线程函数传递参数
std::thread t(printNumber, number);
std::cout << "main thread ID " << std::this_thread::get_id() << std::endl;
t.join();
return 0;
}
需要注意,如果传递的是引用类型参数,要确保在子线程执行期间该引用所指向的对象是有效的,否则可能导致未定义行为。如果想传递引用,可以使用std::ref 或 std::cref
#include <iostream>
#include <thread>
void changeNumber(int& num) {
num += 10;
std::cout << "thread ID " << std::this_thread::get_id() << std::endl;
std::cout << "number: " << num << std::endl;
}
int main() {
int number = 5;
// 使用 std::ref 传递引用
std::thread t(changeNumber, std::ref(number));
std::cout << "main thread ID " << std::this_thread::get_id() << std::endl;
std::cout << "before number: " << number << std::endl;
t.join();
std::cout << "after number: " << number << std::endl;
return 0;
线程分离(detach)
除了 join,还可以使用 detach 将线程与主线程分离,分离后的线程会在后台独立运行,主线程无需等待它结束,也不能再对该线程进行 join 操作。
#include <iostream>
#include <thread>
void test() {
for (int i = 0; i < 5; ++i) {
std::cout << i << std::endl;
}
}
int main() {
std::thread t(test);
// 分离线程
t.detach();
std::cout << "=========" << std::endl;
// 只会输出 =========
return 0;
}
注:使用 detach 时要确保分离的线程所访问的资源在该线程生命周期内始终有效,否则可能引发内存访问错误。
同步机制
多线程环境下,为了避免资源竞争(如多个线程同时访问或者修改共享变量),C++11 还引入了一系列同步工具:
1、互斥锁(std::mutex):
用于保护共享资源,同一时间只有一个线程能获取互斥锁并访问共享资源。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex m_mutex;
int shared_number = 0;
void test() {
for (int i = 0; i < 1000; ++i) {
// 锁定互斥锁
std::lock_guard<std::mutex> guard(m_mutex);
shared_number++;
}
}
int main() {
std::thread t1(test);
std::thread t2(test);
t1.join();
t2.join();
std::cout << "shared_number : " << shared_number << std::endl;
return 0;
}
std::lock_guard 也是一个 RAII(也就是资源获取即初始化)类型,在构造时自动锁定互斥锁,析构时自动解锁,能有效避免忘记解锁导致的死锁问题。
2、条件变量(std::condition_variable):
用于线程间的通信,一个线程可以等待某个条件满足后再继续执行。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m_mutex;
std::condition_variable m_cv;
bool ready = false;
void worker() {
std::unique_lock<std::mutex> lock(m_mutex);
// 等待条件变量满足
m_cv.wait(lock, [] { return ready; });
std::cout << "worker thread is running" << std::endl;
}
int main() {
std::thread t(worker);
// 模拟一些操作后,等待两秒,设置条件为满足
std::this_thread::sleep_for(std::chrono::seconds(2));
{
std::lock_guard<std::mutex> lock(m_mutex);
ready = true;
}
// 通知等待的线程
m_cv.notify_one();
t.join();
return 0;
}
std::condition_variable 通常和 std::mutex 以及 std::unique_lock 配合使用,
m_cv.wait()①当得到锁的线程执行到wait()函数时,当条件不满足,会原子性地释放得到的锁(确保其他线程有机会得到锁);
②而后当前线程进入阻塞状态,等待被唤醒;
③当该线程被notify()或notifyAll()唤醒后,会重新尝试获取锁;
④只有成功重新获取锁后,线程才会从wait()方法返回,继续执行后续代码
3、原子类型(std::atomic):
提供了无锁的原子操作,对于一些简单的共享变量操作(如整数的增减),使用原子类型可以避免加锁带来的性能开销。
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<int> number(0);
void test() {
for (int i = 0; i < 1000; ++i) {
number++;
}
}
int main() {
std::thread t1(test);
std::thread t2(test);
t1.join();
t2.join();
std::cout << "number : " << number << std::endl;
return 0;
}
小结
- 线程管理:
std::thread创建线程,支持join()(等待结束)、detach()(后台运行),get_id()获取线程标识 - 同步机制:
-
std::mutex互斥锁,配合lock_guard/unique_lock管理临界区std::condition_variable实现线程等待 / 通知(wait()/notify_one()/notify_all())std::atomic提供无锁原子操作
- 核心价值:能够跨平台统一接口,原生支持多线程,融合了现代 C++ 特性(比如 lambda),简化了并发编程
更多推荐



所有评论(0)