当前位置: 首页 > news >正文

C++11QT复习 (十九)

文章目录

    • Day13 C++ 时间库和线程库学习笔记(Chrono 与 Thread)
      • 一、时间库 `<chrono>`
        • 1.1 基本概念
        • 1.2 使用示例
        • 1.3 duration 字面量单位
      • 二、线程库 `<thread>`
        • 2.1 基本用法
        • 2.2 数据竞争(Race Condition)
        • 2.3 加锁:互斥锁 `std::mutex`
        • 2.4 示例:单线程与多线程性能对比
          • 单线程版本
          • 多线程 + 共享内存(未加锁)
          • 多线程 + 加锁
          • 优化版:每线程局部求和后再加总(锁移出循环)
      • 三、线程安全总结
      • 四、调试建议
      • 五、参考资源

Day13 C++ 时间库和线程库学习笔记(Chrono 与 Thread)

一、时间库 <chrono>

1.1 基本概念

C++ 的 <chrono> 时间库中包含三个核心概念:

  • Clock(时钟):提供当前时间的来源,常用的有:
    • system_clock:系统时间,可转换为 time_t 类型(适合打印日志)
    • steady_clock:单调时钟,适合测量时间间隔(不受系统时间修改影响)
    • high_resolution_clock:高精度时钟,底层通常等同于 steady_clock
  • time_point(时间点):代表某个时钟上的具体时刻。
  • duration(时间段):表示两个时间点之间的时间差。
1.2 使用示例
#include <chrono>
#include <iostream>
#include <ctime>
#include <thread>

void wait_or_sleep_for_or_until() {
    using namespace std::chrono_literals; // 支持 1s, 10ms 等单位

    std::this_thread::sleep_for(1s); // 睡眠1秒(使用 duration 类型)
    std::this_thread::sleep_until(std::chrono::high_resolution_clock::now() + 1s); // 睡眠到某时间点
}

void calculate_execution_time() {
    auto before = std::chrono::high_resolution_clock::now();
    // 执行某段代码
    auto after = std::chrono::high_resolution_clock::now();

    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
    std::cout << "Elapsed: " << elapsed.count() << " ms\n";
}

int main() {
    auto now = std::chrono::system_clock::now();
    std::time_t now_c = std::chrono::system_clock::to_time_t(now);
    std::cout << "Current time: " << std::ctime(&now_c);
}
1.3 duration 字面量单位

使用 std::chrono_literals 命名空间后支持:

  • h, min, s, ms, us, ns

二、线程库 <thread>

2.1 基本用法

创建线程的方式:

std::thread t(func); // 执行 func()
t.join();  // 等待线程结束
t.detach(); // 让线程独立运行,主线程不再等待

线程函数可以使用 lambda 表达式,支持传入引用:

int x = 10;
std::thread t([&x] { x += 5; });
t.join();
2.2 数据竞争(Race Condition)

多个线程同时修改共享变量(如 sum)会引发数据竞争,结果不确定。

2.3 加锁:互斥锁 std::mutex
std::mutex mtx;
mtx.lock();
sum += value;
mtx.unlock();

推荐使用 std::lock_guard 实现 RAII 风格的自动加锁解锁:

std::lock_guard<std::mutex> lock(mtx);
sum += value; // 自动解锁
2.4 示例:单线程与多线程性能对比
单线程版本
void single_thread() {
    auto data = generate_data();
    unsigned long long sum = 0;
    Timer clock;

    for (const auto& array : data) {
        for (int i : array) {
            // 计算密集操作(模拟)
            sum += i;
        }
    }
    std::cout << "single_thread: " << clock.duration() << " sum: " << sum << "\n";
}
多线程 + 共享内存(未加锁)
void race_condition_of_shared_memory() {
    unsigned long long sum = 0;
    std::vector<std::thread> threads;
    for (const auto& array : data) {
        threads.emplace_back([&] {
            for (int i : array) sum += i; // 存在数据竞争!
        });
    }
    for (auto& t : threads) t.join();
}
多线程 + 加锁
void mutex_version() {
    std::mutex mtx;
    unsigned long long sum = 0;
    for (...) {
        threads.emplace_back([&] {
            for (...) {
                std::lock_guard<std::mutex> lock(mtx);
                sum += i;
            }
        });
    }
}
优化版:每线程局部求和后再加总(锁移出循环)
void mutex_out_of_loop() {
    std::mutex mtx;
    unsigned long long sum = 0;
    for (...) {
        threads.emplace_back([&] {
            unsigned long long local_sum = 0;
            for (...) local_sum += i;
            std::lock_guard<std::mutex> lock(mtx);
            sum += local_sum;
        });
    }
}

三、线程安全总结

方案是否安全性能说明
单线程安全无并发
多线程(无加锁)不安全快但错误数据竞争
多线程 + 每次加锁安全锁粒度太小
多线程 + 聚合后加锁安全推荐方案,锁粒度大、代价低

四、调试建议

  • 建议使用 Debug 模式运行,避免 release 模式优化导致时间测不准。
  • 保持线程 join/detach 的正确性,避免程序异常终止。
  • 避免栈内存分配超大数组,可使用 std::vector<std::array<>> 放在堆上。

五、参考资源

  • zhihu chrono 详解
  • C++ Concurrency In Action (书籍)

相关文章:

  • 大模型本地部署系列(2) Ollama部署DeepSeek-R1
  • Spring Security 的核心配置项详解,涵盖认证、授权、过滤器链、HTTP安全设置等关键配置,结合 Spring Boot 3.x 版本最佳实践
  • 数据校验和错误处理的方法与策略
  • Linux网络编程——TCP协议格式、可靠性分析
  • RHCSA Linux系统 vim 编辑器
  • Postman的内网使用教程
  • Python基础(一)
  • 重学Java基础篇—Java 反射机制及其用途
  • 记金仓数据库的一次优化
  • 中兴B860AV1.1-T2/B860AV2.2/B860AV2.2U-中星微ZX296716斜片芯片-刷机包及教程
  • 【rdma tx data flow问题】
  • Go语言比较递归和循环执行效率
  • 01背包 Java
  • 复现QGIS-MCP教程
  • 《从单体到分布式:一个订单系统的架构升级》
  • 第37次CCF计算机软件能力认证 / T4 / 集体锻炼
  • 创建 Pod 失败,运行时报错 no space left on device?
  • 3. git config
  • 《AI换脸时代的攻防暗战:从技术滥用走向可信未来》
  • AIGC时代的新风口!MCP协议引领未来无限可能
  • 苹果给第三方网站做图标/百度信息流广告平台
  • 电商设计师自我介绍/seo网上培训课程
  • 赣州北京网站建设/整合营销传播方案案例
  • 免费自动网页生成器/重庆百度推广seo
  • 漳州企业网站建设制作/贵州整站优化seo平台
  • @安徽网站建设/怎样推广自己的商城