windows中互斥体到底什么时候释放?

问题描述 投票:0回答:1

我成功使用了使用

CreateMutex
创建的互斥锁,并将
bInitialOwner
设置为
TRUE
,以确保仅单个应用程序实例运行,多次运行,不会出现任何问题。

我的期望是,这也将扩展到允许最多两个同时运行的实例。这是我旨在实现这一目标的代码:

#include <windows.h>
#include <synchapi.h>

#include <codecvt>
#include <chrono>
#include <iostream>
#include <thread>

int main() {
    std::cout << "New instance started.\n";

    HANDLE mutex_handle = CreateMutexW(0, TRUE, L"myMutex1");
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        std::cout << "At least one instance is already running.\nChecking if this is the second instance...\n";

        HANDLE mutex_handle2 = CreateMutexW(0, TRUE, L"myMutex2");

        if (GetLastError() == ERROR_ALREADY_EXISTS) {
            std::cout << "A second instance also exists already.\n";
        }
    }

    // In every case wait for 25 seconds to simulate a long running program (e.g. GUI, etc.).
    std::this_thread::sleep_for(std::chrono::milliseconds(25000));

    return 0;
}

打开程序三次后,我在第三次实例中得到了所需的输出:

New instance started.
At least one instance is already running.
Checking if this is the second instance...
A second instance also exists already.

但是,即使关闭了除一个打开的实例之外的所有实例(为了简单起见,假设除了第三个实例之外的所有实例都已关闭),我仍然得到上面的输出,而不是预期的:

New instance started.

但是,关闭所有实例后,程序将再次按预期运行。这让我相信,互斥体只有在所有实例关闭后才会被释放,但是文档指出:

使用 CloseHandle 函数关闭句柄。当进程终止时系统自动关闭句柄。当互斥对象的最后一个句柄关闭时,该对象将被销毁。

因此,我希望互斥体在其所属进程终止后就会被释放。

为什么情况似乎并非如此?我如何使用互斥体将我的应用程序限制为两个实例?

附加信息

我的怀疑是,每个后续线程也通过调用

CreateMutexW
获取了一个句柄,因此只有当最后一个句柄关闭时,互斥体才会被销毁(例如,“批处理”的最后一个运行实例被关闭,并且没有更多实例正在运行) .

为了缓解这种情况,我认为只要遇到 CloseHandle

 ,我就可以使用线程获得的句柄调用 
ERROR_ALREADY_EXISTS
 。实现此功能的代码如下,但这会导致与上述完全相同的行为:

#include <windows.h>
#include <synchapi.h>

#include <codecvt>
#include <chrono>
#include <iostream>
#include <thread>

int main() {
    std::cout << "New instance started.\n";

    HANDLE mutex_handle = CreateMutexW(0, TRUE, L"myMutex1");
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        if (mutex_handle != NULL)
        {
            CloseHandle(mutex_handle);
        }

        std::cout << "At least one instance is already running.\nChecking if this is the second instance...\n";

        HANDLE mutex_handle2 = CreateMutexW(0, TRUE, L"myMutex2");
        if (GetLastError() == ERROR_ALREADY_EXISTS) {
            if (mutex_handle2 != NULL)
            {
                CloseHandle(mutex_handle2);
            }
            
            std::cout << "A second instance also exists already.\n";
        }
    }

    // In every case wait for 25 seconds to simulate a long running program (e.g. GUI, etc.).
    std::this_thread::sleep_for(std::chrono::milliseconds(25000));

    return 0;
}
c++ windows winapi operating-system
1个回答
0
投票

互斥锁仅处于活动或非活动状态。如果您希望传递非二进制数量的等待调用,则可以使用专门为此设计的原语,例如 semaphores,它可以定义要传递的最大调用数量(在您的情况下为 2)。

这种方法的唯一问题是,与互斥体不同,您还需要处理应用程序关闭(以减少信号量计数,以便另一个实例可以“进入”)。一般来说,如果您一次需要 2 个实例,则没有理由不允许任意数量的实例。

© www.soinside.com 2019 - 2024. All rights reserved.