使用bInitialOwner = true的CreateMutex似乎表现得很奇怪

时间:2012-02-12 23:47:47

标签: c multithreading winapi mutex

我真的很茫然。 我彻底阅读了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被简单地忽略)。

1 个答案:

答案 0 :(得分:4)

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

您可以通过不使用bInitialOwner或仅跳过第一个循环上的WaitForSingleObject 来避免这种情况,如果只有GetLastError() != ERROR_ALREADY_EXISTS的话。如果您选择后者,则需要在SetLastError(0)之前致电CreateMutex以清除错误代码。

如果您只需要bInitialOwner进行某种初始设置,如果在进入公共循环之前删除互斥锁,它将简化您的代码。否则,我强烈建议您不要使用bInitialOwner,除非您有令人信服的理由这样做。