互斥(Mutex)是一种用途非常广泛的内核对象。能够保证多个线程对同一共享资源的互斥访问。同临界区有些类似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。与其他几种内核对象不同,互斥对象在操作系统中拥有特殊代码,并由操作系统来管理,操作系统甚至还允许其进行一些其他内核对象所不能进行的非常规操作。只有拥有互斥对象并得以进入到共享资源,而其他线程则会被排斥在外。当此线程处理完共享资源并准备离开此区域时将把其所拥有的互斥对象交出,其他任何一个试图访问此资源的线程都有机会得到此互斥对象。
基本介绍
CMutex类的对象代表“哑程(mutex)”——它为一个同步对象,允许某线程共同访问同一资源。在仅仅一个
线程被允许用于修改数据或其它被控制的资源时,哑程将变得非常有用。例如,给链接的列表增添一个结点就是只允许一个线程的过程。通过使用CMutex对象来控制链接列表,此时只有一个线程能够获得列表的访问权。
若要使用CMutex 对象,首先要构造一个所需的CMutex 对象。然后指定希望等待的哑程的名称,那么应用最初就将拥有它。可以在
构造函数返回时,访问哑程。当你已经访问了被控制的资源后,再调用CSyncObject::
Unlock函数。
另外一种使用CMutex 对象的方法就是一个CMutex类型的
变量,将其作为你希望
控制类的
数据成员。在被控制对象的构造过程中,若哑程最初拥有了哑程的名称或期待的安全属性,那么就调用CMutex数据成员指定的构造函数,以这种方式访问由CMutex 对象控制的资源,首先要在资源访问的成员函数中创建CSingleLock类型或CMultiLock类型的变量。然后调用封锁对象的Lock成员函数(例如, CSingleLock::Lock)。这样,你的线程要么就获得资源的访问权,以等待将要释放的资源,并获取访问权,要么就等待将要释放的资源,当超时后,返回失败。在任何一种情况下,都可以在
线程安全的模式下访问资源。若要释放这些资源,使用封锁对象的Unlock成员函数(例如, CSingleLock::Unlock),或允许封锁对象越界。
CMutex类
1、CMutex只是对 win32API 的互斥操作进行了封装
2、它的参数与 win32 API 中的 CreatMutex() 相对应
3、CMutex的构造函数调用 CreatMutex() 创建并检查
4、其Lock操作从基类继承,调用WaitForSingleObject()获得所有权,互斥类重载 Unlock 调用ReleaseMutex()释放所有权。
所以,MFC其实就是简单了封装了 win32 API 函数。
实现
1、CMutex::CMutex(BOOL bInitiallyOwn, LPCTSTR pstrMame)
2、CMutex::~CMutex()
3、BOOL CMutex::Unlock()
使用和用法
首先,创建工程——win32 console Application——工程名——OK——an application that supports MFC——finish
CMutex mutex; //声明互斥
UINT mythreadA:mutex.Lock();
//动作
mutex.Unlock();
Sleep(1000);
UINT mythreadB:mutex.Lock();
//动作
mutex.Unlock();
Sleep(1000);
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)通过某个成员函数访问被 CMutex 对象保护的资源(即array[1024];)时,要创建CSingleLock或者是CMultiLock,它以 CMutex 对象的指针为参数。
(2)然后调用 CSingleLock或CMultiLock的成员函数Lock()和Unlock()来获取和释放资源
(3)这样,在一个进程使用该类时,就不必担心同步问题了。
#include
class CResourse //定义资源类
{
private:
int array[1024];
CMutex mutex; //此时互斥量受到保护
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(&mutex);
sLock.Lock();
if(sLock.IsLocked())
array[n]=data;
sLock.Unlock();
}
int CResourse::getdata(int n)
{
int t;
CSingleLock sLock(&mutex);
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<
int main(int argc, TCHAR* argv[], TCHAR* envp[] )
{
AfxBeginThread(mythread1,NULL);
AfxBeginThread(mythread2,NULL);
Sleep(1000);
return 1;
}
小结
上面两个例子的区别主要是:
1、一个是CMutex的单独使用,一个是CMutex和CSingleLock一起使用。
2、第一个是关于同步的问题;
3、第二个是关于资源类受到保护的问题。受到保护时,需要用CSingleLock或CMultiLock 间接访问。