一、Windows的互斥锁Mutex是什么?
1、为Windows内核对象
2、实现进程或线程的互斥/同步
3、实现为Windows的一组API
二、Windows的互斥锁各接口
1、CreateMutex函数
作用:创建互斥对象,并获取互斥对象的void句柄;或者获取互斥对象的void句柄。
a、原型:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
b、接口说明:
lpMutexAttributes:指向SECURITY_ATTRIBUTES结构的指针
- 如果此参数为 NULL,则子进程无法继承句柄。结构的 lpSecurityDescriptor 成员为新的互斥指定安全描述符。 如果lpMutexAttributes为NULL,则mutex获取默认的安全描述符。
bInitialOwner:创建互斥对象的进程\线程A是否占有权
- TRUE:占有,FALSE:不占有;
- 一般为FALSE,不为任何进程\线程所占用;
- 若为TRUE,表希望A占有该互斥对象,若真正创建了该互斥对象,则无论A是否拿到锁,它进程\线程B中的wait函数将阻塞,直到A调用CloseHandle或消亡后,B中的wait函数才会返回WAIT_ABANDONED(128L)。
lpName:指向互斥对象名的字符串指针
- 名称区分大小写;
- 如果为 NULL,则会在没有名称的情况下创建互斥对象,将无法实现进程间同步;
- 可添加全局”或“本地”前缀,如"Local\name"和"Global\name",以便应用程序能够支持多个用户。
返回值:指向互斥对象的void*句柄
- 如执行成功,返回互斥体对象的句柄,NULL表示出错;
- 一般情况,无论指定的名字互斥对象是否已经存在,都能成功拿到有效的void*句柄;
- 若指定的名字互斥对象是否已经存在,则不会初始化新的互斥对象,GetLastError返回ERROR_ALREADY_EXISTS(183L),等同于调用OpenMutex函数。
2、OpenMutex
作用:获取互斥对象的void*句柄。
a、原型:
HANDLE OpenMutex(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
b、接口说明:
dwDesiredAccess:对互斥对象访问期望权限
- 请指定MUTEX_ALL_ACCESS。
bInheritHandle:子进程能够继承句柄
- 若为TRUE,则由此进程创建的进程将继承句柄;
- 若为FALSE,子进程不会继承此句柄。
lpName:指向互斥对象名的字符串指针
- 与CreateMutex同
返回值:指向互斥对象的void*句柄
- 如果函数成功,则返回值是互斥对象的void*句柄;
- 如果函数失败,则返回值为 NULL;如果命名互斥体不存在,该函数将失败,GetLastError返回ERROR_FILE_NOT_FOUND(2L)。
3、WaitForSingleObject
作用:获取互斥锁
a、原型:
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
b、接口说明:
hHandle:指向互斥对象的void*句柄
- CreateMutex或OpenMutex函数的返回值。
dwMilliseconds:超时间隔(以毫秒为单位)
- 如果指定了非零值,该函数将等待对象发出信号或间隔;
- 如果dwMilliseconds为零,则如果对象未发出信号,则函数不会输入等待状态;它始终会立即返回;
- 如果dwMilliseconds为INFINITE,则仅当发出对象信号时,该函数才会返回。
返回值:指示导致函数返回的事件
- WAIT_OBJECT_0(0L),成功获取互斥锁;
- WAIT_TIMEOUT(258L),等待超时;
- WAIT_FAILED(0xFFFFFFFF),函数失败。 要获得更多的错误信息,请调用 GetLastError;
- WAIT_ABANDONED(128L),见上文“1、CreateMutex --> b、接口说明:–> bInitialOwner的第三条”。
4、ReleaseMutex
作用:解锁
a、原型:
BOOL ReleaseMutex(
HANDLE hHandle,
);
b、接口说明:
hHandle:指向互斥对象的void*句柄
- CreateMutex或OpenMutex函数的返回值。
返回值:解锁是否成功
调用成功返回TRUE,此时另一个在等待该mutex的进程\线程,将得到信号停止等待(wait函数)。
例如:
WaitForSingleObject(hMutex,INFINITE); hMutex对象如果变为激发状态,这个函数就会返回,继续往下执行。
5、CloseHandle
作用:释放内核对象副本
BOOL CloseHandle(
HANDLE hObject,
);
b、接口说明:
hHandle:指向互斥对象的void*句柄
- CreateMutex或OpenMutex函数的返回值。
返回值:解锁是否成功
关闭一个句柄,并将这个句柄的引用计数减一,如果句柄的引用计数减到0,那么操作系统将释放这个核心对象的句柄。用CloseHandle来释放Mutex时,只是释放当前进程获得的句柄,而不会删除该Mutex内核对象。
三、Windows的进程互斥锁使用说明
1、不可跨PC
2、当多个进程对计算机上的同一份文件进行操作时候,需要对文件进行保护,防止多个进程同时对文件进行修改造成错误,因此可采用Windows的互斥锁Mutex来进行加锁。
// CreatMutex.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
//打开进程锁
HANDLE hmutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, TEXT("MutexTest"));
//创建进程锁
if (hmutex == NULL)
{
cout<<"Create MutexTest!"<<endl;
hmutex = CreateMutex(NULL, false, TEXT("MutexTest"));
}
//获取进程锁
DWORD ts = WaitForSingleObject(hmutex, INFINITE);
if (WAIT_OBJECT_0 == ts)
{
// 进行数据操作,下面是简单举例
for (int i=0; i<10; i++)
{
cout << i <<endl;
Sleep(1000);
}
}
// 操作完成后释放进程锁
ReleaseMutex(hmutex);
if (hmutex != NULL)
{
CloseHandle(hmutex);
}
return 0;
}
四、需要注意的问题
如果一个进程A(线程A):HANDLE hMutexA=CreateMutex(NULL,true,“MyAppMutex”);创建了一个互斥体;
同时另一个进程B(线程B)也:HANDLE hMutexB=CreateMutex(NULL,true,“MyAppMutex”);这个时候hMutexB会得到已经存在的互斥体的句柄吗?
答:不会,而是接口成功会返回该互斥锁的句柄。但是可以通过GetLastError返回ERROR_ALREADY_EXISTS(183L)。
如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.youkuaiyun.com/qq_43148810