一、具体实现:
_AFXMT_INLINE CCriticalSection::CCriticalSection()
_AFXMT_INLINE CCriticalSection::operator CRITICAL_SECTION*()
_AFXMT_INLINE CCriticalSection::~CCriticalSection()
_AFXMT_INLINE BOOL CCriticalSection::Lock()
_AFXMT_INLINE BOOL CCriticalSection::Lock(DWORD )
_AFXMT_INLINE BOOL CCriticalSection::Unlock()
二、与互斥量比较
1、和CMutex类相似,也分两种情况:单独使用,和CSingleLock使用。
2、它们能用在单个进程内的线程间同步,但互斥量除此之外还可以在多个进程间的线程同步。
3、从性能上讲,临界段要优于互斥量。
三、例子
1、单独使用(伪代码)
CCriticalSection section;//声明临界段
int arr[10]; //共享变量
Thread A: section.Lock();
//访问,操作共享变量
section.Unlock();
Thread B: section.Lock();
//访问,操作共享变量
section.Unlock();
int _tmain():int flag=0;
if(!AfxWinInit(::GetModuleHandle(NULL),NULL,::GetCommandLine(),0))
{cerr<<.......... ; flag=1; }
else
{
AfxBeginThread(mythreadA,NULL);
AfxBeginThread(mythreadB,NULL);
Sleep(10000);
}
return flag;
这个操作和互斥量的单独使用的操作是一模一样的。
2、和CSingleLock配合的使用:
1)通过某个成员函数访问被 CCriticalSection 对象保护的资源(即array[1024];)时,要创建CSingleLock或者是CMultiLock,它以 CCriticalSection 对象的指针为参数。
2)然后调用 CSingleLock或CMultiLock的成员函数Lock()和Unlock()来获取和释放资源
3)这样,在一个进程使用该类时,就不必担心同步问题了。
#include"afxmt.h"//同步操作时需要包含的头文件
#include<iostream.h>
class CResourse //定义资源类
{
private:
int array[1024];
CCriticalSection section; //此时临界段受到保护
public:
CResourse();//构造函数
~CResourse();//析构函数
void setdata(int n ,int data);
int getdata(int n);
}
//以下为资源类内的公共函数初始化
CResourse::CResourse:mutex(FALSE,NULL)
{ for(int i=0;i<1024;i++) array[i]=0; }
CResourse::~CResourse() {}
void CResourse::setdata(int n, int data)
{
CSingleLock sLock(§ion);//以临界段为参数
sLock.Lock();
if(sLock.IsLocked())
array[n]=data;
sLock.Unlock();
}
int CResourse::getdata(int n)
{
int t;
CSingleLock sLock(§ion);//以临界段为参数
sLock.Lock();
if(sLock.IsLocked())
t=array[n];
sLock.Unlock();
return t;
}
UINT mythread1(LPVOID pParam);
UINT mythread2(LPVOID pParam);
CResourse res; //声明全局变量
UINT mythread1(LPVOID pParam);
{ res.setdata(1,100); retuen 1; }
UINT mythread2(LPVOID pParam);
{ cout<<res.getdata(1)<<endl; retuen 1; }
int main(int argc, TCHAR* argv[], TCHAR* envp[] )
{
AfxBeginThread(mythread1,NULL);
AfxBeginThread(mythread2,NULL);
Sleep(1000);
return 1;
}
以上这个例子,也是和互斥类的和CSingleLock配合使用的例子一模一样。
3、关于银行中客户获取ID的问题,也可以用 MFC 临界段来实现
#include"afxmt.h"//同步操作时需要包含的头文件
#include<iostream.h>
class Identifier //定义资源类
{
private:
unsigned int m_id;;
CCriticalSection section; //此时临界段受到保护
public:
unsigned int getID();
}
//以下为资源类内的公共函数初始化
unsigned int Identifier::getID()
{
unsigned int id;
CSingleLock sLock(§ion);
sLock.Lock();
id = m_id;
m_id++;
sLock.Unlock();
return id;
}
Identifier globalID; //声明全局变量
unsigned long _stdcall mythread(LPVOID pParam);
{ int id = globalID.getID(); cout<<id<<""; retuen 1; }
int main(int argc, TCHAR* argv[], TCHAR* envp[] )
{
HANDLE handle;
DWORD dw;
for(int i=0;i<100;i++)
{
handle = CreateThread(NULL,0,mythread,NULL,0,&dw);
CloseHandle(handle);
}
Sleep(6000);
return 0;
}
四、小结
上面两个例子的区别主要是:
1、一个是CCriticalSection的单独使用,二个是CCriticalSection和CSingleLock一起使用,三是根据情况使用并更新临界段内的资源。
2、例子1是关于同步的问题;
3、例子2 是关于资源类受到保护的问题。受到保护时,需要用CSingleLock或CMultiLock 间接访问。