【原】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 @   bugless6481  阅读(1522)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
关注我的博客
点击右上角即可分享
微信分享提示