我真的很茫然。
我已仔细阅读了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/