• 2022-08-20 C++并发编程(十三)



    前言

    通过时钟类我们可以方便的查看程序运行时长,在程序优化时很有用处。结合条件变量,可以实现有条件逻辑的限时等待。同时支持限时等待的还有互斥,可以完成某些纯限时等待的简单逻辑。


    一、记录程序执行时间

    将要执行函数放在两个时间点之间,求得时间差。

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    // using namespace std::chrono_literals;
    
    void doSomething()
    {
        std::this_thread::sleep_for(
            std::chrono::duration<int, std::ratio<1, 1>>(2));
        std::cout << "doSomething" << std::endl;
    }
    
    auto main() -> int
    {
        auto start = std::chrono::high_resolution_clock::now();
        doSomething();
    
        auto stop = std::chrono::high_resolution_clock::now();
    
        auto durations =
            // std::chrono::duration
            std::chrono::duration<double, std::ratio<1, 1>>
            // std::chrono::duration_cast
            (stop - start).count();
    
        std::cout << "doSometing() took " << durations << " seconds" << std::endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    二、使用条件变量的限时等待成员函数

    条件变量的限时等待函数 cv.wait_until(lk, timeout),阻塞线程,放开锁 lk,直至等到 timeout 时间点,或其他线程的通知,持有锁,进行下一步执行语句。

    为了防止伪唤醒导致直接略过含有条件变量的 if 语句,需要将 if 语句嵌套在 while 循环中。

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    std::condition_variable cv;
    
    bool done;
    
    std::mutex m;
    
    auto waitLoop() -> bool
    {
        auto const timeout =
            std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
    
        std::unique_lock<std::mutex> lk(m);
    
        while (!done)
        {
            if (cv.wait_until(lk, timeout) == std::cv_status::timeout)
            {
                std::cout << "break" << std::endl;
                break;
            }
        }
    
        return done;
    }
    
    auto main() -> int
    {
        waitLoop();
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    三、限时等待的互斥

    std::timed_mutex 是可限时等待的互斥,利用其成员函数 try_lock_for(times) 可以在 times 时间之内试图加锁,也可用成员函数 try_lock_until(timePoint),在某时间点前尝试加锁。

    以下示例可以更改 std::chrono::duration> Seconds(4) 以及
    auto timePoint = std::chrono::system_clock::now() + std::chrono::duration>(5)
    的值查看获取锁的情况。

    #include 
    #include 
    #include 
    #include 
    
    std::timed_mutex tm;
    
    std::chrono::duration<double, std::ratio<1, 1>> Seconds(4);
    
    void waitFor(int times, int id)
    {
        bool locks = tm.try_lock_for(Seconds);
    
        std::this_thread::sleep_for(
            std::chrono::duration<long, std::ratio<1, 1>>(times));
    
        if (locks)
        {
            std::cout << "unlockTryLockFor" << id << std::endl;
            locks = false;
            tm.unlock();
        }
    }
    
    void waitUntil()
    {}
    
    auto main() -> int
    {
    
        std::thread waitForTime1(waitFor, 2, 1);
    
        std::thread waitForTime2(waitFor, 2, 2);
    
        auto timePoint = std::chrono::system_clock::now() + std::chrono::duration<long, std::ratio<1, 1>>(5);
    
        std::this_thread::sleep_for(
            std::chrono::duration<long, std::ratio<1, 1>>(1));
    
        bool locks = tm.try_lock_until(timePoint);
    
        if (locks)
        {
            std::cout << "unlockTryLockUntil\n";
            tm.unlock();
            locks = false;
        }
    
        waitForTime1.join();
        waitForTime2.join();
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    总结

    限时等待在多线程并发编程的作用是梳理程序的时间线逻辑,以完成某些有关时效性的程序逻辑实现,可粗略的分为两类,等待一段时间(for),或等到某个时间点(until)。单独使用并不复杂,和其他程序逻辑搭配,会复杂不少,还需仔细斟酌。

    参考文献:C++并发编程实战(第2版)[英] 安东尼•威廉姆斯(Anthony Williams)

  • 相关阅读:
    学习大数据DAY33 Flask 库 API 开发介绍,OS 库,pandas 库和简单爬虫
    Fair原理篇之Fair逻辑动态化通信实现
    系统权限-数据权限案例分析
    Android Studio开发入门教程:如何更改APP的图标?
    DETR纯代码分享(四)misc.py
    泛函分析(二)巴纳赫(Banach)不动点,贝尔曼方程(Bellman equation)在强化学习的应用
    axios配置代理ip
    flume之Ganglia的部署
    Python 实验六 文件访问
    c++中类和对象(1)
  • 原文地址:https://blog.csdn.net/m0_54206076/article/details/126444107