【原】MFC多线程之互斥量Mutex

先看模拟火车售票的这个程序:

#include "windows.h"
#include <iostream.h>//线程头文件

DWORD WINAPI ThreadProc1(LPVOID lpParameter);
DWORD WINAPI ThreadProc2(LPVOID lpParameter);
int index=0;
int ticket=100;
HANDLE hMutex;//一个互斥量
void main()
{
	HANDLE hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);//创建线程,放回HANDLE
	HANDLE hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
	CloseHandle(hThread1);//我们对返回的HANDLE 不关心,要释放,否则计数器会+1
	CloseHandle(hThread2);
	//while(index++<1000)
//	cout<<"main is running"<<endl;
	hMutex=CreateMutex(NULL,FALSE,NULL);//TRUE 表示创建他的拥有他。即主线程拥有这个对象
//你一个参数为安全机制:NULL,第二个为FALSE表示手动指定拥有者,若为TRUE,其拥有者为创建他的进程,这里为main函数
//即主线程 Sleep(4000); } DWORD WINAPI ThreadProc1(LPVOID lpParameter) { // while(index++<1000) // cout<<"Thread1 is running"<<endl; while(TRUE) { WaitForSingleObject(hMutex,INFINITE);//等待互斥量的信号 if(ticket>0) { Sleep(1); cout<<"Thread1 sell ticket"<<ticket--<<endl; } else break; ReleaseMutex(hMutex); } return 0; } DWORD WINAPI ThreadProc2(LPVOID lpParameter) { //while(index++<1000) // cout<<"Thread1 is running"<<endl; while(TRUE) { //互斥有id,会吃对象 WaitForSingleObject(hMutex,INFINITE); if(ticket>0) { Sleep(1); cout<<"Thread2 sell ticket"<<ticket--<<endl; } else break; ReleaseMutex(hMutex);//释放 } return 0; }

  假如为CreateMutex第二个参数为TRUE,表示主线程拥有它,hMutex=CreateMutex(NULL,TRUE,NULL);//TRUE 表示创建他的拥有他。即主线程拥有这个对象

  要是其他线程获得Mutex,必须先要释放:ReleaseMutex(hMutex);//释放

  即:替换红色代码:hMutex=CreateMutex(NULL,TRUE,NULL);ReleaseMutex(hMutex);

     再加入红色代码如下:hMutex=CreateMutex(NULL,TRUE,NULL);WaitForSingleObject(hMutex,INFINITE);ReleaseMutex(hMutex) 

   

  主线程创建Mutex,并且拥有它,然后在等待Mutex,这样,Mutex中线程ID为主线程,计数器为2,所以,你只释放一次,其他线程无法获得互斥对象有信号状态

所以,一直都是主线程在运行。

  或许你想说,我现在ThreadProc1中的WaitForSingleObject(hMutex,INFINITE);前加一句ReleaseMutex(hMutex) ;是ta在释放一次就行了。。。。答案是否定的,因为现在的互斥对象内部的线程ID为主线程ID号,所以,其他线程不能释放,也就无法请求了。。。。。。

   注意,操作系统会判断线程是否结束来自释放Muetex,可以看waiforsingleObject的返回值来判断Mutex是正常释放还是由于线程结束:

 

Return code/valueDescription
WAIT_ABANDONED
0x00000080L
The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled.

If the mutex was protecting persistent state information, you should check it for consistency.

WAIT_OBJECT_0
0x00000000L
The state of the specified object is signaled.
WAIT_TIMEOUT
0x00000102L
The time-out interval elapsed, and the object's state is nonsignaled.
代码改成这样子:
View Code
#include "windows.h"
#include <iostream.h>

DWORD WINAPI ThreadProc1(LPVOID lpParameter);
DWORD WINAPI ThreadProc2(LPVOID lpParameter);
int index=0;
int ticket=100;
HANDLE hMutex;
void main()
{
    HANDLE hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
    HANDLE hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);
    CloseHandle(hThread1);
    CloseHandle(hThread2);
    //while(index++<1000)
//    cout<<"main is running"<<endl;
    //hMutex=CreateMutex(NULL,FALSE,NULL);//TRUE 表示创建他的拥有他。即主线程拥有这个对象
    hMutex=CreateMutex(NULL,TRUE,"Ticket");
    if(hMutex)
    {
        if(ERROR_ALREADY_EXISTS==GetLastError())//已经被创建
        {
            cout<<"Only instance is runing"<<endl;
            return ;
        }
    }
    WaitForSingleObject(hMutex,INFINITE);//计数器为2
    ReleaseMutex(hMutex);
    ReleaseMutex(hMutex);//释放两次
    Sleep(4000);
}
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
//    while(index++<1000)
    //    cout<<"Thread1 is running"<<endl;
    while(TRUE)
    {
        WaitForSingleObject(hMutex,INFINITE);
        if(ticket>0)
        {
            Sleep(1);
            cout<<"Thread1 sell  ticket"<<ticket--<<endl;
        }
        else 
            break;
        ReleaseMutex(hMutex);
    }
    return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
    //while(index++<1000)
    //    cout<<"Thread1 is running"<<endl;
    while(TRUE)
    {
        //互斥有id,会吃对象
        WaitForSingleObject(hMutex,INFINITE);
        if(ticket>0)
        {
            Sleep(1);
            cout<<"Thread2 sell  ticket"<<ticket--<<endl;
        }
        else 
            break;
        ReleaseMutex(hMutex);
    }
    return 0;
}

如果你运行两次程序,第二次就会弹出only instance is runing

原因是:Mutex命名互斥,当hMutex有值,所以已经创建了这个Mutex,就创建了一个程序,

当getLastError==ERROR_AlREADY_EXITS,说明重复

if(ERROR_ALREADY_EXISTS==GetLastError())//已经被创建
        {
            cout<<"Only instance is runing"<<endl;
            return ;
        }

 

posted @ 2013-04-20 01:01  bugless6481  阅读(1500)  评论(0编辑  收藏  举报
关注我的博客