为了使用一个Windows 互斥体(无论是像您这样的命名还是未命名的),您需要使用以下 Win API:
<1234564> <1234563>CreateMutex
- 获取互斥体 Windows kernel object 的句柄。如果是命名互斥锁(如您的),多个进程应该成功获取此句柄。第一个将导致操作系统创建一个新的命名互斥体,而其他人将获得一个指向同一个互斥体的句柄。如果您获得了指定互斥锁的有效句柄,您可以通过检查
GetLastError
是否返回ERROR_ALREADY_EXISTS
来确定互斥锁是否已经存在(即另一个进程已经创建了互斥锁)。<1234563>
WaitForSingleObject
- 锁定互斥锁以进行独占访问。这个函数实际上并不特定于互斥锁,它被用于许多内核对象。有关 Windows 内核对象的更多信息,请参阅上面的链接。<1234563>
ReleaseMutex
- 解锁互斥锁。<1234563>
CloseHandle
- 释放获取的互斥量句柄(与 Windows 句柄一样)。当进程存在时,操作系统会自动关闭句柄,但***明确地执行此操作。
一个完整的例子:
#include <Windows.h>
#include <iostream>
int main()
{
// Create the mutex handle:
HANDLE hMutex = ::CreateMutex(nullptr, FALSE, L"SingleInstanceMutex");
if (!hMutex)
{
std::cout << "Failed to create mutex handle." << std::endl;
// Handle error: ...
return 1;
}
bool bAlreadyExisted = (GetLastError() == ERROR_ALREADY_EXISTS);
std::cout << "Succeeded to create mutex handle. Already existed: " << (bAlreadyExisted ? "YES" : "NO") << std::endl;
// Lock the mutex:
std::cout << "Atempting to lock ..." << std::endl;
DWORD dwRes = ::WaitForSingleObject(hMutex, INFINITE);
if (dwRes != WAIT_OBJECT_0)
{
std::cout << "Failed to lock the mutex" << std::endl;
// Handle error: ...
return 1;
}
std::cout << "Locked." << std::endl;
// Do something that required the lock: ...
std::cout << "Press ENTER to unlock." << std::endl;
std::getchar();
// Unlock the mutex:
if (!::ReleaseMutex(hMutex))
{
std::cout << "Failed to unlock the mutex" << std::endl;
// Handle error: ...
return 1;
}
std::cout << "Unlocked." << std::endl;
// Free the handle:
if (!CloseHandle(hMutex))
{
std::cout << "Failed to close the mutex handle" << std::endl;
// Handle error: ...
return 1;
}
return 0;
}
错误处理:
正如您在上面的文档链接中所见,当CreateMutex
、ReleaseMutex
和CloseHandle
失败时,您应该调用GetLastError
以获取有关该错误的更多信息。 WaitForSingleObject
将在出错时返回一个特定的返回值(参见上面的文档链接)。这应该作为// Handle error: ...
部分的一部分来完成。
笔记:
为 IPC(进程间通信)使用命名互斥锁可能是本机 Windows 互斥锁的唯一好用例。
对于常规的未命名互斥锁,***使用可用的标准库类型之一的互斥锁:std::mutex
,std::recursive_mutex
,std::recursive_timed_mutex
(最后两个支持线程重复锁定,类似于 Windows 互斥锁)。
【讨论】:
- <1234563>
CreateMutex
是创建了新的互斥体还是返回了对现有互斥体的引用。至于有效的用例,Windows 原生互斥体具有与std::mutex
不同的属性,即拥有互斥体的线程可以重复等待它。 std::recursive_timed_mutex
将是更接近的匹配。尽管您可能应该使用SRW Lock 来代替。