1、windows临界区
临界区又称关键代码段,指的是一小段代码在代码执行前,它需要独占一些资源。
1.1 相关函数
(1)初始化
程序中通常将多线程同时访问的某个资源作为临界区,需要定义一个CRITICAL_SECTION类型的变量,然后调用InitializeCriticalSection函数对变量进行初始化;
函数原型:VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection );
参数说明:lpCriticalSection:一个CRITICAL_SECTION结构指针,表示用于初始化的临界区;
InitializeCriticalSection函数在内部设置了CRITICAL_SECTION结构的某些成员变量,所以它不会失败。
(2)定义临界区
为了将某一段代码定义为临界区,需要调用EnterCriticalSection函数;
函数原型:VOID WINAPI EnterCriticalSection(__inout LPCRITICAL_SECTION lpCriticalSection);
该函数的作用是判断是否有线程访问临界区资源:
- 如果没有,就改变CRITICAL_SECTION结构的成员变量的值,赋予当前线程访问权,函数立即返回;
- 如果有线程正在访问资源,则进入等待状态,直到没有线程访问。
(3)释放资源
函数原型:void WINAPI LeaveCriticalSection( _Inout_LPCRITICAL_SECTION lpCriticalSection);
(4)释放CRITICAL_SECTION结构指针
函数原型:void WINAPI DeleteCriticalSection(_Inout_ LPCRITICAL_SECTION lpCriticalSection);
1.2 类示例
#ifndef CAUTO_LOCK_H__
#define CAUTO_LOCK_H__
class CAutoLock
{
public:
CAutoLock();
~CAutoLock();
void Lock();
void UnLock();
private:
CRITICAL_SECTION m_Section;
};
#endif
#include "stdafx.h"
#include "CAutoLock.h"
CAutoLock::CAutoLock()
{
InitializeCriticalSection(&m_Section);
//Lock();如果是用的时候只定义锁对象,可以不手动进入临界区和退出临界区
}
CAutoLock::~CAutoLock()
{
DeleteCriticalSection(&m_Section);
//UnLock();
}
void CAutoLock::Lock()
{
EnterCriticalSection(&m_Section);
}
void CAutoLock::UnLock()
{
LeaveCriticalSection(&m_Section);
}
注意:
在“同一个线程”(不同线程会卡住等待),windows中的“相同临界区变量”代表的临界区的进入可以被调用多次。
调用几次锁住,就要调用几次释放。
而在C++11中的mutex不允许调用多次,否则会报异常。
自动析构技术:编写一个类,直接可以使用于锁定和解锁临界区
class CWinLock
{
public:
CWinLock(CRITICAL_SECTION *pCritmp) //构造函数
{
m_pCritical = pCritmp;
EnterCriticalSection(m_pCritical);
}
~CWinLock()
{
LeaveCriticalSection(m_pCritical); //析构函数
}
private:
CRITICAL_SECTION *m_pCritical;
};
int main()
{
CWinLock wlock(&my_winsc);
}
2、其他mutex互斥量
2.1 递归mutex
std::mutex独占互斥量,自己lock时别人lock不了。
std::recursive_mutex递归的独占互斥量,允许同一线程,同一个互斥量被多次lock,效率比mutex差一些。
2.2 带超时的互斥量
(1)std::timed_mutex
- try_lock_for:等待一段时间,如果拿到锁或者等待超时没拿到锁,就往下走。
- try_lock_until:是一个未来的时间点,在这个未来的时间没到的时间内,如果拿到了锁就往下走;如果时间到了,没拿到锁程序流程也往下走。
(2)std::recursive_timed_mutex
带超时功能的递归独占互斥量(允许同一个线程多次获取这个互斥量)。