💡 C++ 标准库笔记(时间库 & 线程库)
📅 Part 1:时间库 <chrono>
🧩 基本概念
C++ 的 <chrono> 库提供了用于处理时间点(time_point)、时间段(duration) 和 时钟(clock) 的类模板,是处理时间相关操作的标准方式。
| 概念 | 简介 |
|---|
clock | 时钟,用于获取当前时间 |
time_point | 一个具体的时间点 |
duration | 表示两个时间点之间的时间段 |
⏰ 常用时钟类型
| 时钟类型 | 说明 |
|---|
std::chrono::system_clock | 系统当前时间,可以转换为 time_t(适合日志) |
std::chrono::steady_clock | 单调时钟,适合计时,不受系统时间影响 |
std::chrono::high_resolution_clock | 高精度计时器,通常是 steady_clock 的别名 |
auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::cout << std::ctime(&now_c);
🧮 计时器使用示例
auto start = std::chrono::high_resolution_clock::now();
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "耗时:" << duration.count() << " 毫秒\n";
🕒 线程延时操作
引入字面量单位
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
std::this_thread::sleep_until(std::chrono::high_resolution_clock::now() + 2s);
🧵 Part 2:线程库 <thread> 和同步工具 <mutex>
🚀 基础用法:std::thread
- 创建线程时需要提供一个可调用对象(函数、lambda、函数对象等)。
- 线程启动后立即运行,直到结束或主线程
join() 或 detach()。
std::thread t([] {
std::cout << "Thread is running\n";
});
t.join();
👬 join 与 detach 区别
| 方法 | 含义 |
|---|
join() | 主线程等待子线程执行完 |
detach() | 子线程脱离主线程独立运行,不能再 join,生命周期由系统控制 |
| ❗注意 | 若线程在析构前未 join 或 detach,程序将 terminate() |
🔒 线程安全与同步:std::mutex
🚧 为什么需要锁
多个线程读写共享变量(如 sum)会导致数据竞争(race condition),造成不可预知的错误结果或崩溃。
unsigned long long sum = 0;
std::mutex mtx;
auto thread_func = [&]() {
std::lock_guard<std::mutex> lock(mtx);
sum += 1;
};
✅ 推荐使用 std::lock_guard
RAII 风格自动管理锁,异常安全,推荐使用。
std::lock_guard<std::mutex> lock(mtx);
🧠 多线程案例分析
✅ 单线程执行(对照组)
for (const auto& array : vector) {
for (int i : array) {
sum += i;
}
}
❌ 多线程 + 共享变量(无锁)→ 错误结果
threads.push_back(std::thread([&sum, &array] {
for (int i : array) {
sum += i;
}
}));
✅ 使用 mutex 保护(但效率低)
std::mutex mtx;
threads.push_back(std::thread([&sum, &array, &mtx] {
for (int i : array) {
std::lock_guard<std::mutex> lock(mtx);
sum += i;
}
}));
✅ 优化:局部变量累加后再锁一次
std::mutex mtx;
threads.push_back(std::thread([&sum, &array, &mtx] {
unsigned long long local_sum = 0;
for (int i : array) {
local_sum += i;
}
std::lock_guard<std::mutex> lock(mtx);
sum += local_sum;
}));
🧠 补充知识点
🧮 栈溢出风险
- 栈是线程的私有资源,大小有限。
std::array<int, 5000000> 太大会导致栈溢出,应放入堆中(如 std::vector<std::array<...>>)。
🧪 std::asin, std::acos, std::atan, std::sqrt
- 为了制造“有用但无意义”的运算负载。
- 用于模拟真实计算,提高 benchmark 的可信度。
✨ 编码建议 & 小技巧
__FUNCTION__ 宏:打印当前函数名(含命名空间)。- 使用
constexpr 设定常量,提升可读性和效率。 - 尽量避免在循环中频繁加锁,可采用局部变量聚合后统一加锁。
🔚 总结:学习路线建议
| 学习阶段 | 建议内容 |
|---|
| 初学者 | 掌握 std::thread, std::mutex, std::lock_guard 基础使用方法 |
| 进阶者 | 熟悉竞态条件调试、优化加锁策略、合理使用 sleep_for, sleep_until |
| 拓展学习 | 学习 std::future, std::promise, std::condition_variable 等更复杂的同步机制 |