转:http://hi.baidu.com/emad1211/blog/item/1a4dbaecafec6b4279f05528.html
在工程文件中, WinMain函数里加上以下代码(此代码在BCB6.0下运行):
进程的互斥运行
正常情况下,一个进程的运行一般是不会影响到其他正在运行的进程的。但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的,而且此类程序通常也不允许运行同一个程序的多个实例。这就引出了进程互斥的问题。
实现进程互斥的核心思想比较简单:进程在启动时首先检查当前系统是否已经存在有此进程的实例,如果没有,进程将成功创建并设置标识实例已经存在的标记。此后再创建进程时将会通过该标记而知晓其实例已经存在,从而保证进程在系统中只能存在一个实例。具体可以采取内存映射文件、有名事件量、有名互斥量以及全局共享变量等多种方法来实现。下面就分别对其中具有代表性的有名互斥量和全局共享变量这两种方法进行介绍:
上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为:
如果函数成功执行,将返回一个互斥量对象的句柄。如果在CreateMutex()执行前已经存在有相同名字的互斥量,函数将返回这个已经存在互斥量的句柄,并且可以通过GetLastError()得到错误代码ERROR_ALREADY_EXIST。可见,通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex()对进程的互斥。
建立互斥体,用来同步。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
参数
lpMutexAttributes
指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。
bInitialOwner
布尔类型,决定互斥体的创建者是否为拥有者
lpName
指向互斥体名字字符串的指针。互斥体可以有名字。
互斥体的好处是可以在进程间共享
心得体会:
CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行,或不允许同名程序运行)。如有同名程序运行,则通过 GetLastError()得到错误代码 ERROR_ALREADY_EXIST。
刚才又执行了下得出的结果(程序名samp)
一般情况下:一进入调试阶段,进程管理器中就出现了samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,跳过不执行if中的内容,所以表示没有互斥。
调试之前先运行debug中的samp.exe再调试:一进入调试阶段,进程管理器中就出现了两个samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,执行if中的内容,表示有互斥。
HANDLE winMutex; class WinMutex: public Runnable { public: void run() { while (1) { DWORD r = WaitForSingleObject(winMutex,INFINITE); switch(r) { case WAIT_OBJECT_0: std::cout << "thread return." << std::endl; Thread::sleep(100); ReleaseMutex(winMutex); Thread::sleep(100); break; default: std::cout << "error" << std::endl; } } } }; int main() { winMutex = CreateMutexA(NULL, /* 默认属性 */ FALSE, /* 有信号状态 */ NULL); /* 没有名字 */ Thread t1; WinMutex R; t1.start(R); Thread::sleep(100); DWORD r = WaitForSingleObject(winMutex,INFINITE); if (r == WAIT_OBJECT_0) std::cout << "main return." << std::endl; Thread::sleep(100); ReleaseMutex(winMutex); Thread::sleep(100); r = WaitForSingleObject(winMutex,INFINITE); if (r == WAIT_OBJECT_0) std::cout << "main return." << std::endl; return 0; }
CreateMutex时,第二个参数是FALSE,即没有拥有者,所以处于有信号状态。那个线程先WaitForSingleObject到,就占用这个Mutex,使其处于无信号状态,其他wait的线程就阻塞;当ReleaseMutex后,Mutex又回到有信号状态,其他wait 的线程可以继续运行。
输出结果
可以看见,主函数和另一个线程是交替wait到Mutex,交替运行的。