C++并发与多线程(十一)windows临界区、recursive_mutex、timed_mutex

windows临界区

windows临界区是在windows编程中的内容,了解一下即可,效果几乎可以等同于c++11的mutex;windows编程仅能在windows操作系统中使用,其它环境(例如linux)是不能正常运行的。

使用方法:

//包含头文件
#include <Windows.h>

CRITICAL_SECTION m_winsec; //windwos临界区定义

InitializeCriticalSection(&m_winsec); //windows临界区使用之前,必须初始化

EnterCriticalSection(&my_winsec);	//	进入临界区
//需要加锁的代码...
LeaveCriticalSection(&my_winsec);	//	离开临界区


  1. 包含头文件#include< windows.h >;
  2. 定义临界区变量:CRITICAL_SECTION m_winsec;
  3. 初始化临界区(使用之前必须初始化)InitializeCriticalSection(&m_winsec)
  4. 进入和离开临界区EnterCriticalSection(&my_winsec)LeaveCriticalSection(&my_winsec)对应的就是mutex的lock()unlock()

windows临界区的特点:

  1. 相较于mutex互斥量,Windows临界区,同一个线程是可以重复进入的,但是进入的次数与离开的次数必须相等;C++互斥量则不允许同一个线程重复加锁。

  2. windows中的临界区同mutex一样,可以保护一个代码段。但windows的临界区可以进入多次,离开多次,但是进入的次数与离开的次数必须相等,不会引起程序报异常出错。

自动析构技术

之前在中讲过,用类实现自动释放互斥量,这里类似的方法,实现自动释放windows临界区,相当于实现一个windows临界区版的lock_guard():

class CWinLock {
public:
    CWinLock(CRITICAL_SECTION *pCritmp)
    {
        my_winsec =pCritmp;
        EnterCriticalSection(m_winsec);
    }
    ~CWinLock()
    {
        LeaveCriticalSection(m_winsec)
    };
private:
    CRITICAL_SECTION *m_winsec;
};

上述这种类RAII类(Resource Acquisition is initialization),即资源获取及初始化。容器,智能指针属于这种类。

std::recursive_mutex

recursive_mutex是一个递归的独占互斥量,它用来解决的问题是,mutex不能连续两次调用lock()(windows临界区可以做到)。

std::mutex: 独占式互斥量
std::recursive_mutex:允许在同一个线程中同一个互斥量多次被 lock(),(但是递归加锁的次数是有限制的,太多可能会报异常),效率要比mutex低。

但是必须用recursive_mutex,一定要考虑一下代码是否有优化空间,如果能调用一次 lock()就不要调用多次

std::timed_mutex

std::timed_mutex是待超时的独占互斥量,他有两个方法:try_lock_for()try_lock_until()

1.try_lock_for()

try_lock_for()是等待一段时间,如果拿到了锁,或者超时了未拿到锁,就继续执行(有选择执行)

std::timed_mutex m_mutex; //定义一个timed_mutex变量

std::chrono::milliseconds timeout(100);
if (m_mutex.try_lock_for(timeout)){
    //......拿到锁返回ture
}
else{
    std::chrono::milliseconds sleeptime(100);
    std::this_thread::sleep_for(sleeptime);
}

2.try_lock_until()

参数是一个未来的时间点,在这个未来的时间没到的时间内,如果拿到了锁头,流程就走下来,如果时间到了没拿到锁,流程也可以走下来。

std::timed_mutex m_mutex; //定义一个timed_mutex变量

std::chrono::milliseconds timeout(100);
if (m_mutex.try_lock_until(chrono::steady_clock::now() + timeout)){
    //......拿到锁返回ture
}
else{
    std::chrono::milliseconds sleeptime(100);
    std::this_thread::sleep_for(sleeptime);
}
  1. 两种方法的本质区别就是一个参数是时间段,一个参数是时间点
  2. 不仅mutex有超时的类,递归的mutex也有对应的超时类std::recursive_timed_mutex,与timed_mutex用法完全一致,灵活使用即可。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值