C++并发与多线程编程–windows临界区、其他mutex互斥量

  • Post author:
  • Post category:其他





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

带超时功能的递归独占互斥量(允许同一个线程多次获取这个互斥量)。



版权声明:本文为locahuang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。