C++并发之定时互斥(std::timed_mutex)

1 概述

  定时互斥是一种时间可锁定的对象,它设计用于在代码的关键部分需要独占访问时发出信号,就像常规互斥一样,但还支持定时尝试锁定请求。
  因此,timed_mutex有两个额外的成员:try_lock_for和try_lock_until。
它保证是一个标准布局类。 标准布局类型是一种具有简单线性数据结构和访问控制的类型,可以很容易地用于与用其他编程语言(如C)编写的代码进行通信.
其类图如下:
在这里插入图片描述

2 使用实例

struct TimedFunction
{
    volatile int counter = 0;
    void fireworks(std::timed_mutex & muxtex)
    {
        while(!muxtex.try_lock_for(std::chrono::milliseconds(200)))
            ;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        ++counter;
        muxtex.unlock();
    }

    void waitUtil(std::timed_mutex & muxtex, int seconds)
    {
        std::chrono::time_point<std::chrono::system_clock> timePoint 
            = std::chrono::system_clock::now() + std::chrono::seconds(seconds);
        std::cerr << "\n\nWait util " << seconds << " seconds... \n";
        if(muxtex.try_lock_until(timePoint))
        {
            muxtex.unlock();
            counter = 10;
        }
        else
            counter = 5;
    }
    void sleepFor(std::timed_mutex & muxtex, int seconds)
    {
        muxtex.lock();
        std::cerr << "\n\nSleep " << seconds << " seconds... \n";
        std::this_thread::sleep_for(std::chrono::seconds(seconds));
        muxtex.unlock();
    }
};

void TimedMutexSuite::try_lock_for()
{
    std::timed_mutex muxtex;
    TimedFunction function;
    std::thread threads[10];
    for(int i = 0; i < 10; i++)
        threads[i] = std::thread(&TimedFunction::fireworks, std::ref(function), std::ref(muxtex));
    for(auto &thread : threads)
        thread.join();
    TEST_ASSERT_EQUALS(true, function.counter == 10)
    std::cerr << "function.counter: " << function.counter << std::endl;
}

void TimedMutexSuite::try_lock_until()
{
    std::timed_mutex muxtex;
    TimedFunction function;
    std::thread threads[2];

    threads[0] = std::thread(&TimedFunction::sleepFor, std::ref(function), std::ref(muxtex), 10);
    threads[1] = std::thread(&TimedFunction::waitUtil, std::ref(function), std::ref(muxtex), 5);

    threads[0].join();
    threads[1].join();
    TEST_ASSERT_EQUALS(true, function.counter == 5)

    threads[0] = std::thread(&TimedFunction::sleepFor, std::ref(function), std::ref(muxtex), 5);
    threads[1] = std::thread(&TimedFunction::waitUtil, std::ref(function), std::ref(muxtex), 10);

    threads[0].join();
    threads[1].join();
    TEST_ASSERT_EQUALS(true, function.counter == 10)
}

3 接口使用

3.1 construct

void addCount(std::timed_mutex & mutex, int & count)
{
    mutex.lock();
    count++;
    mutex.unlock();
}

void TimedMutexSuite::construct()
{
    std::timed_mutex muxtex;
    int count = 0;
    std::thread threads[10];
    for(int i = 0; i < 10; i++)
        threads[i] = std::thread(addCount, std::ref(muxtex), std::ref(count));
    for(auto &thread : threads)
        thread.join();
    TEST_ASSERT_EQUALS(10, count)   
}

3.2 lock

void TimedMutexSuite::lock()
{
    std::timed_mutex muxtex;
    int count = 10;
    std::thread threads[10];
    for(int i = 0; i < 10; i++)
        threads[i] = std::thread(addCount, std::ref(muxtex), std::ref(count));
    for(auto &thread : threads)
        thread.join();
    TEST_ASSERT_EQUALS(20, count)   
}

3.3 try_lock

struct TimedFunction
{
    volatile int counter = 0;
    void add_10k_count(std::timed_mutex & muxtex)
    {
        for(int i = 0; i < 10000; i++)
        {
            if(muxtex.try_lock())
            {
                ++counter;
                muxtex.unlock();
            }
        }
    }
};

void TimedMutexSuite::try_lock()
{
    std::timed_mutex muxtex;
    TimedFunction function;
    std::thread threads[10];
    for(int i = 0; i < 10; i++)
        threads[i] = std::thread(&TimedFunction::add_10k_count, std::ref(function), std::ref(muxtex));
    for(auto &thread : threads)
        thread.join();
    TEST_ASSERT_EQUALS(true, function.counter < (10 * 10000))
    std::cerr << "function.counter: " << function.counter << std::endl;
}

3.4 try_lock_for

struct TimedFunction
{
    volatile int counter = 0;

    void fireworks(std::timed_mutex & muxtex)
    {
        while(!muxtex.try_lock_for(std::chrono::milliseconds(200)))
            ;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        ++counter;
        muxtex.unlock();
    }

    void waitUtil(std::timed_mutex & muxtex, int seconds)
    {
        std::chrono::time_point<std::chrono::system_clock> timePoint 
            = std::chrono::system_clock::now() + std::chrono::seconds(seconds);
        std::cerr << "\n\nWait util " << seconds << " seconds... \n";
        if(muxtex.try_lock_until(timePoint))
        {
            muxtex.unlock();
            counter = 10;
        }
        else
            counter = 5;
    }
    void sleepFor(std::timed_mutex & muxtex, int seconds)
    {
        muxtex.lock();
        std::cerr << "\n\nSleep " << seconds << " seconds... \n";
        std::this_thread::sleep_for(std::chrono::seconds(seconds));
        muxtex.unlock();
    }
};
void TimedMutexSuite::try_lock_for()
{
    std::timed_mutex muxtex;
    TimedFunction function;
    std::thread threads[10];
    for(int i = 0; i < 10; i++)
        threads[i] = std::thread(&TimedFunction::fireworks, std::ref(function), std::ref(muxtex));
    for(auto &thread : threads)
        thread.join();
    TEST_ASSERT_EQUALS(true, function.counter == 10)
    std::cerr << "function.counter: " << function.counter << std::endl;
}

说明:

  • try_lock_for 如果等待指定时间没有锁定返回false,否则返回true

3.5 try_lock_until

void TimedMutexSuite::try_lock_until()
{
    std::timed_mutex muxtex;
    TimedFunction function;
    std::thread threads[2];

    threads[0] = std::thread(&TimedFunction::sleepFor, std::ref(function), std::ref(muxtex), 10);
    threads[1] = std::thread(&TimedFunction::waitUtil, std::ref(function), std::ref(muxtex), 5);

    threads[0].join();
    threads[1].join();
    TEST_ASSERT_EQUALS(true, function.counter == 5)

    threads[0] = std::thread(&TimedFunction::sleepFor, std::ref(function), std::ref(muxtex), 5);
    threads[1] = std::thread(&TimedFunction::waitUtil, std::ref(function), std::ref(muxtex), 10);

    threads[0].join();
    threads[1].join();
    TEST_ASSERT_EQUALS(true, function.counter == 10)
}

说明:

  • try_lock_until 如果等到指定时间没有锁定返回false,否则返回true

3.6 unlock

void TimedMutexSuite::unlock()
{
    std::timed_mutex muxtex;
    int count = 20;
    std::thread threads[10];
    for(int i = 0; i < 10; i++)
        threads[i] = std::thread(addCount, std::ref(muxtex), std::ref(count));
    for(auto &thread : threads)
        thread.join();
    TEST_ASSERT_EQUALS(30, count)   
}

相关推荐

  1. C++并发编程】(三)互斥锁:std::mutex

    2024-06-18 23:02:04       34 阅读
  2. Golang 并发 Mutex 互斥锁的使用

    2024-06-18 23:02:04       30 阅读
  3. C++多线程编程】(一)详解互斥锁mutex

    2024-06-18 23:02:04       58 阅读
  4. 【3】c++多线程技术线程同步与互斥

    2024-06-18 23:02:04       33 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-18 23:02:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-18 23:02:04       101 阅读
  3. 在Django里面运行非项目文件

    2024-06-18 23:02:04       82 阅读
  4. Python语言-面向对象

    2024-06-18 23:02:04       91 阅读

热门阅读

  1. 音频处理2_进阶概念

    2024-06-18 23:02:04       39 阅读
  2. Git分支打包的详细教程

    2024-06-18 23:02:04       26 阅读
  3. ubuntu22.04安装vivado2022.2

    2024-06-18 23:02:04       34 阅读
  4. Ubuntu Updates for this repository will not be applied

    2024-06-18 23:02:04       25 阅读
  5. ijkplayer编译 android版本

    2024-06-18 23:02:04       38 阅读
  6. QT

    QT

    2024-06-18 23:02:04      30 阅读
  7. ARM处理器的应用场景

    2024-06-18 23:02:04       31 阅读
  8. adb 截屏和录屏命令

    2024-06-18 23:02:04       27 阅读
  9. 数据库设计规范总结

    2024-06-18 23:02:04       27 阅读
  10. ubuntu20.04安装配置openMVG+openMVS

    2024-06-18 23:02:04       24 阅读
  11. PostgreSQL源码分析——CREATE SERVER

    2024-06-18 23:02:04       23 阅读