• 【原】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 ;
            }
  • 相关阅读:
    easyui-tabs扩展根据自定义属性打开页签
    nhibernate 3.x新特性
    c# dynamic的属性是个变量
    草稿
    好番记录
    今日内容
    PHP Filter
    PHP Filesystem
    PHP Directory 函数
    PHP Date/Time 函数
  • 原文地址:https://www.cnblogs.com/dakou/p/3031872.html
Copyright © 2020-2023  润新知