我真的很茫然。
我已仔细阅读了MSDN文章,但仍无法弄清楚发生了什么。
我的问题是:使用以下代码运行一些进程时,它们都正常工作:

HANDLE m = CreateMutex(NULL, FALSE, L"MyMutex");
char c[20] = "2print";
for(int iter = 0; iter<100; ++iter) {
    WaitForSingleObject(m,INFINITE);
    for(int i=0;i<(int)strlen(c);++i) {
           for(int j=0;j<10000;++j)
                 printf("%c",c[i]);
    }
    BOOL ok = ReleaseMutex(m);
}
CloseHandle(m);

也就是说,不同的处理过程会轮流进行每次打印,并释放互斥锁,直到完成所有打印为止。

但是将CreateMutex更改为:(bInitialOwner从FALSE更改为TRUE)
HANDLE m = CreateMutex(NULL, TRUE, L"MyMutex");

第一个创建者将不会释放互斥锁!其他过程就在那里。
令我惊讶的是,通过添加一个额外的releaseMutex,它正在发生变化:
BOOL ok = ReleaseMutex(m);

进入:
BOOL ok = ReleaseMutex(m);
ok = ReleaseMutex(m);

让它起作用!

我真的很困惑,为什么第一个创建者不会正确释放互斥锁?
我尝试使用GetLastError打印所有错误,并且得到的结果似乎是合理的,例如对于第一个创建者之后的ERROR_ALREADY_EXISTS,这正是我所期望的(MSDN表示,在这种情况下,bInitialOwner被忽略了)。

最佳答案

当您使用bInitialOwner=TRUE时,互斥量创建者会自动获取互斥量。然后,当您调用WaitForSingleObject时,它将再次获取互斥量。由于win32互斥锁是递归互斥锁,因此每次获取互斥锁时必须释放一次-因此初始创建者需要两次ReleaseMutex调用(但是每个其他线程只能释放一次!)

您可以通过不使用bInitialOwner或仅在WaitForSingleObject时仅在第一个循环中跳过GetLastError() != ERROR_ALREADY_EXISTS来避免这种情况。如果选择错误代码,则需要先调用SetLastError(0),然后再调用CreateMutex,以清除错误代码。

如果只需要bInitialOwner进行某种初始设置,如果在进入公共(public)循环之前放下了互斥对象,它将简化代码。否则,除非您有充分的理由,否则我强烈建议您不要使用bInitialOwner

关于c - 带有bInitialOwner = true的CreateMutex似乎很奇怪,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9253860/

10-13 06:28