我真的很茫然。 我彻底阅读了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被简单地忽略)。
答案 0 :(得分:4)
使用bInitialOwner=TRUE
时,互斥锁创建者会自动获取互斥锁。然后,当您致电WaitForSingleObject
时,它再次获得了互斥锁 。由于win32互斥锁是递归互斥锁,因此每次获取互斥锁时都必须释放一次 - 因此初始创建者需要两次ReleaseMutex
次调用(但是每个其他线程只能释放一次!)
您可以通过不使用bInitialOwner
或仅跳过第一个循环上的WaitForSingleObject
来避免这种情况,如果只有GetLastError() != ERROR_ALREADY_EXISTS
的话。如果您选择后者,则需要在SetLastError(0)
之前致电CreateMutex
以清除错误代码。
如果您只需要bInitialOwner
进行某种初始设置,如果在进入公共循环之前删除互斥锁,它将简化您的代码。否则,我强烈建议您不要使用bInitialOwner
,除非您有令人信服的理由这样做。