c++ 11 std::recursive_timed_mutex递归锁定的互斥,并实现有时限锁定

定义于头文件 <mutex>

std::recursive_timed_mutex

class recursive_timed_mutex;            (C++11 起) 

recursive_timed_mutex 是同步原语,能用于保护共享数据免受从多个线程同时访问。

以类似 std::recursive_mutex 的方式, recursive_timed_mutex 提供排他性递归所有权语义。另外, recursive_timed_mutex 通过 try_lock_fortry_lock_until 方法,提供带时限地试图要求 recursive_timed_mutex 所有权的能力。

recursive_timed_mutex 类满足定时互斥体 (TimedMutex) 和标准布局类型 (StandardLayoutType) 的所有要求。

构造函数

recursive_timed_mutex();        (1) (C++11 起) 

recursive_timed_mutex( const recursive_timed_mutex& ) = delete;  (2) (C++11 起) 

1) 构造互斥。调用后互斥在未锁定状态。

2) 复制构造函数被删除。

参数

(无)

异常

若构造不成功则抛出 std::system_error 。

析构函数

~recursive_timed_mutex();

销毁互斥。

若互斥为任何线程占有,或若任何线程在保有任何互斥的所有权时终止,则行为未定义。

解锁互斥

void unlock();             (C++11 起) 

若所有权等级为 1 (此线程对 lock() 的调用恰好比 unlock() 多一次 )则解锁互斥,否则将所有权等级减少 1 。

互斥必须为当前执行线程所锁定,否则行为未定义。

此操作同步于(定义于 std::memory_order )任何后继的取得同一互斥所有权的锁操作。

参数

(无)

返回值

(无)

异常

(无)

注意

通常不直接调用 unlock() :用 std::unique_lock 与 std::lock_guard 管理排他性锁定。

锁定互斥,若互斥不可用则阻塞

void lock();                 (C++11 起) 

锁定互斥。若另一线程已锁定互斥,则到 lock 的调用将阻塞执行,直至获得锁。

线程可以在递归互斥上重复调用 lock 。在线程调用 unlock 匹配数量次后,所有权才会得到释放。

所有权的最大层数是未指定的。若超出此数,则可能抛 std::system_error 类型异常。

同一互斥上先前的 unlock() 操作同步于(定义于 std::memory_order )此操作。

参数

(无)

返回值

(无)

异常

错误发生时抛出 std::system_error ,包括底层操作系统阻止 lock 满足其规定的错误。在抛出任何异常的情况下,不锁定互斥。

注意

通常不直接调用 lock() :用 std::unique_lock 与 std::lock_guard 管理排他性锁定。

调用示例

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>

int g_num = 0;  // 为 g_num_mutex 所保护
std::recursive_timed_mutex g_num_mutex;

void slow_increment(int id)
{
    for (int i = 0; i < 3; ++i) {
        g_num_mutex.lock();
        ++g_num;
        std::cout << id << " => " << g_num << '\n';
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    for (int i = 0; i < 3; ++i)
    {
        g_num_mutex.unlock();
    }
}

int main()
{
    std::thread t1(slow_increment, 0);
    std::thread t2(slow_increment, 1);
    t1.join();
    t2.join();
}

输出

尝试锁定互斥,若互斥不可用则返回

bool try_lock();                 (C++11 起) 

尝试锁定互斥。立即返回。成功获得锁时返回 true ,否则返回 false 。

允许此函数虚假地失败而返回 false ,即使互斥当前未为任何其他线程所锁定。

线程可以重复调用 try_lock 。到 try_lock 的成功调用自增所有权计数:线程调用 unlock 匹配次数后互斥才会得到释放。

所有权层数的最大值是未指定的。若超出此数,则到 try_lock 的调用将返回 false 。

若此操作返回 true ,则同一互斥上的先前 unlock() 操作同步于(定义于 std::memory_order )它。注意若此操作返回 false ,则先前的 lock() 不与之同步。

参数

(无)

返回值

若成功取得锁则为 true ,否则为 false 。

异常

(无)

调用示例

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>


int g_num = 0;  // 为 g_num_mutex 所保护
std::recursive_timed_mutex g_num_mutex;

void test_try_lock()
{
    std::recursive_timed_mutex test;
        if (test.try_lock()==true) {
            std::cout << "lock acquired" << std::endl;
            test.unlock();      // 现在锁定互斥
        } else {
            std::cout << "lock not acquired" << std::endl;
        }

        test.lock();    // 再锁定它
        if (test.try_lock()) {  // 可留下 true
            std::cout << "lock acquired" << std::endl;
        } else {
            std::cout << "lock not acquired" << std::endl;
        }
        test.unlock();
}

int main()
{
    std::thread t1(slow_increment, 0);
    std::thread t2(slow_increment, 1);
    t1.join();
    t2.join();
}

输出

尝试锁定互斥,若互斥在指定的时限时期中不可用则返回

template< class Rep, class Period >
bool try_lock_for( const std::chrono::duration<Rep,Period>& timeout_duration );
  (C++11 起) 

尝试锁互斥。阻塞直到经过指定的 timeout_duration 或得到锁,取决于何者先到来。成功获得锁时返回 true , 否则返回 false 。

timeout_duration 小于或等于 timeout_duration.zero() ,则函数表现同 try_lock() 。

由于调度或资源争议延迟,此函数可能阻塞长于 timeout_duration

标准推荐用 steady_clock 度量时长。若实现用 system_clock 代替,则等待时间亦可能对时钟调整敏感。

同 try_lock() ,允许此函数虚假地失败并返回 false ,即使在 timeout_duration 中某点互斥不为任何线程所锁定。

若此操作返回 true ,则同一互斥上先前的 unlock() 调用同步于(定义于 std::memory_order )它。

线程可以在递归互斥上重复调用 try_lock_for 。对 try_lock_for 的成功调用增加所有权计数:仅在线程调用 unlock 匹配次数后才会释放互斥。

所有权等级数的最大值是未指定的。若超出此值,则到 try_lock_for 的调用将返回 false 。

参数

timeout_duration-要阻塞的最大时长

返回值

若成功获得锁则为 true ,否则为 false 。

异常

执行期间时钟、时间点或时长可能抛出的异常(标准库提供的时钟、时间点和时长决不抛出)

调用示例

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <vector>
#include <sstream>

std::mutex cout_mutex; // 控制到 std::cout 的访问
std::recursive_timed_mutex rt_mutex;

void job(int id)
{
    using Ms = std::chrono::milliseconds;
    std::ostringstream stream;

    for (int i = 0; i < 3; ++i) {
        if (rt_mutex.try_lock_for(Ms(100))) {
            stream << "success ";
            std::this_thread::sleep_for(Ms(100));
            rt_mutex.unlock();
        } else {
            stream << "failed ";
        }
        std::this_thread::sleep_for(Ms(100));
    }

    std::lock_guard<std::recursive_timed_mutex> lock(rt_mutex);
    std::cout << "[" << id << "] " << stream.str() << "\n";
}

int main()
{
    std::vector<std::thread> threads;
    for (int i = 0; i < 4; ++i) {
        threads.emplace_back(job, i);
    }

    for (auto& i: threads) {
        i.join();
    }
}

输出

尝试锁定互斥,若直至抵达指定时间点互斥不可用则返回

template< class Clock, class Duration >
bool try_lock_until( const std::chrono::time_point<Clock,Duration>& timeout_time );
  (C++11 起) 

尝试所互斥。阻塞直至抵达指定的 timeout_time 或得到锁,取决于何者先到来。成功获得锁时返回 true ,否则返回 false 。

若已经过 timeout_time ,则此函数表现同 try_lock() 。

使用倾向于 timeout_time 的时钟,这表示时钟调节有影响。从而阻塞的最大时长可能小于但不会大于在调用时的 timeout_time - Clock::now() ,依赖于调整的方向。由于调度或资源争议延迟,函数亦可能阻塞长于抵达 timeout_time 之后。

同 try_lock() ,允许此函数虚假地失败并返回 false ,即使在 timeout_time 前的某点任何线程都不锁定互斥。

若此操作返回 true ,则同一互斥上先前的 unlock() 调用同步于(定义于 std::memory_order )它。

线程可以在递归互斥上重复调用 try_lock_until 。对 try_lock_until 的成功调用增加所有权计数:仅在线程调用 unlock 匹配次数后才会释放互斥。

所有权等级数的最大值是未指定的。若超出此值,则到 try_lock_until 的调用将返回 false 。

参数

timeout_time-要阻塞到的最大时间点

返回值

若成功获得锁则为 true ,否则为 false 。

异常

执行期间时钟、时间点或时长可能抛出的异常(标准库提供的时钟、时间点和时长决不抛出)

调用示例

#include <thread>
#include <iostream>
#include <chrono>
#include <mutex>

std::recursive_timed_mutex test_mutex;

void f()
{
    auto now=std::chrono::steady_clock::now();
    test_mutex.try_lock_until(now + std::chrono::seconds(10));
    std::cout << "hello world\n";
}

int main()
{
    std::lock_guard<std::recursive_timed_mutex> l(test_mutex);
    std::thread t(f);
    t.join();
}

输出

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值