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); // 离开临界区
- 包含头文件
#include< windows.h >
; - 定义临界区变量:
CRITICAL_SECTION m_winsec
; - 初始化临界区(使用之前必须初始化)
InitializeCriticalSection(&m_winsec)
; - 进入和离开临界区
EnterCriticalSection(&my_winsec)
,LeaveCriticalSection(&my_winsec)
对应的就是mutex的lock()
和unlock()
windows临界区的特点:
-
相较于mutex互斥量,Windows临界区,同一个线程是可以重复进入的,但是进入的次数与离开的次数必须相等;C++互斥量则不允许同一个线程重复加锁。
-
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);
}
- 两种方法的本质区别就是一个参数是时间段,一个参数是时间点。
- 不仅mutex有超时的类,递归的mutex也有对应的超时类
std::recursive_timed_mutex
,与timed_mutex用法完全一致,灵活使用即可。